脱壳基础知识入门之Dump内存映像
javadump分析

Java 的线程线程是指能独立于程序的其它部分运行的执行单元。
JAVA语言能够很好的实现多线程的程序。
我们在调试程序,或者在开发后期需要做性能调优的时候,往往也需要了解当前程序正在运行的线程的状态,正在执行的操作,从而分析系统可能存在的问题。
在阅读本文之间,应对Java线程的编程原理,同步机制有一定了解.产生JAVA线程dumpJAVA 的线程DUMP,就象当前JAVA进程的一个快照,打印出所有线程的状态和调用堆栈,以及Monitor的状态。
在不同的操作系统下,产生线程DUMP的方式是不同的。
在启动程序的控制台里敲:Ctrl - Break,线程的dump会产生在标准输出中(缺省标准输出就是控制台,如果对输出进行了重定向,则要查看输出文件)。
在unix,linux 和MacOS 环境中,在控制台中敲:Ctrl-\,或者,用“kill -3 <pid>” ,或者“kill –QUIT <pid>”。
Pid是用所关注的JAVA进程号,您可以用“ps -ef | grep j ava” 找到,或者使用JDK 5.0中的“jps -v” 命令获得。
在各个操作系统平台,都可以用JDK 5.0工具包中的jstack <pid>这里要注意的是:1. 不同的JAVA虚机的线程DUMP的创建方法和文件格式是不一样的,不同的JVM版本,dump信息也有差别。
本文中,只以SUN的hotspot JVM 5.0_06 为例。
2. 在实际运行中,往往一次dump的信息,还不足以确认问题。
建议产生三次dump信息,如果每次dump都指向同一个问题,我们才确定问题的典型性。
线程分析:1. JVM 线程在线程中,有一些JVM内部的后台线程,来执行譬如垃圾回收,或者低内存的检测等等任务,这些线程往往在JVM初始化的时候就存在,如下所示:"Low Memory Detector" daemon prio=10 tid=0x081465f8 nid=0x7 runnable [0x00000000..0x00000000]"CompilerThread0" daemon prio=10 tid=0x08143c58 nid=0x6 waiting on condition [0x00000000..0xfb5fd798]"Signal Dispatcher" daemon prio=10 tid=0x08142f08 nid=0x5 waiting on condition [0x00000000..0x00000000]"Finalizer" daemon prio=10 tid=0x08137ca0 nid=0x4 in Object.wait() [0xfbeed000..0xfbeeddb8]at ng.Object.wait(Native Method)- waiting on <0xef600848> (a ng.ref.ReferenceQueue$Lock)at ng.ref.ReferenceQueue.remove(ReferenceQueue.java:116)- locked <0xef600848> (a ng.ref.ReferenceQueue$Lock)at ng.ref.ReferenceQueue.remove(ReferenceQueue.java:132)at ng.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)"Reference Handler" daemon prio=10 tid=0x081370f0 nid=0x3 in Object.wait() [0xfbf4a000..0xfbf4aa38]at ng.Object.wait(Native Method)- waiting on <0xef600758> (a ng.ref.Reference$Lock)at ng.Object.wait(Object.java:474)at ng.ref.Reference$ReferenceHandler.run(Reference.java:116)- locked <0xef600758> (a ng.ref.Reference$Lock)"VM Thread" prio=10 tid=0x08134878 nid=0x2 runnable"VM Periodic Task Thread" prio=10 tid=0x08147768 nid=0x8 waiting on condition 我们更多的是要观察用户级别的线程,如下所示:"Thread-1" prio=10 tid=0x08223860 nid=0xa waiting on condition [0xef47a000..0xef47ac38]at ng.Thread.sleep(Native Method)at testthread.MySleepingThread.method2(MySleepingThread.java:53)- locked <0xef63d600> (a testthread.MySleepingThread)at testthread.MySleepingThread.run(MySleepingThread.java:35)at ng.Thread.run(Thread.java:595)我们能看到:线程的状态:waiting on condition线程的调用栈线程的当前锁住的资源:<0xef63d600> 这些信息对我们随后的分析都有用处。
《Armadillo1.xx-2.xx-SiliconRealmsToolworks脱壳分析》

脱壳过程:OD载入程序,老规矩插件隐藏OD,忽略所有异常,再添加以下几个异常C0000005(ACCESS VIOLATION)、C000001D(ILLEGAL INSTRUCTION)、C000001E(INVALID LOCK SEQUENCE)、C0000096(PRIVILEGED INSTRUCTION)入口代码:0105A000 N> 60 pushad0105A001 E8 00000000 call NOTEPAD.0105A0060105A006 5D pop ebp0105A007 50 push eax0105A008 51 push ecx0105A009 0FCA bswap edx0105A00B F7D2 not edx0105A00D 9C pushfd下bp OpenMutexA断点shift+F9运行,77E62391 k> 55 push ebp---------中断在这里77E62392 8BEC mov ebp,esp77E62394 51 push ecx77E62395 51 push ecx77E62396 837D 10 00 cmp dword ptr ss:[ebp+10],077E6239A 56 push esi77E6239B 0F84 C2E30100 je kernel32.77E8076377E623A1 64:A1 18000000 mov eax,dword ptr fs:[18]看堆栈0006F710 0103229B /CALL 到OpenMutexA 来自NOTEPAD.010322950006F714 001F0001 |Access = 1F00010006F718 00000000 |Inheritable = FALSE0006F71C 0006FDA0 \MutexName = "52C:A9EEE0AC4"------注意0006fda0,等下会用到0006F720 000000040006F724 000000000006F728 010476B3 NOTEPAD.010476B3Ctrl+G 01001000 键入以下代码:为什么是Ctrl+G 01001000呢?很多教程里都是Ctrl+G 401000,在本例Ctrl+G 401000是无法写入调式程序中的,而且401000处有代码(大家可以试一试),那么如何知道是用Ctrl+G 01001000的呢?个人认为是根据载入口的代码来确定的,形式是入口代码地址的前3位+01000,如本例中的入口代码是:0105A000 N> 60 pushad,取其地址中的前3位010,再加上01000,合起来就是01001000。
几种用OD脱壳方法

方法四:一步到达OEP
1.开始按Ctrl+F,输入:popad(只适合少数壳,包括UPX,ASPACK壳),然后按下F2,F9运行到此处
2.来到大跳转处,点下F8,到达OEP!
方法五:最后一次异常法
1:用OD打开软件
2:点击选项——调试选项——异常,把里面的√全部去掉!CTRL+F2重载下程序
6:按F2下断点!然后按SHIFT+F9来到断点处! 7:去掉断点,按F8慢慢向下源自! 8:到达程序的OEP!
方法六:模拟跟踪法
1:先试运行,跟踪一下程序,看有没有SEH暗桩之类
2:ALT+M打开内存镜像,找到(包含=SFX,imports,relocations)
内存镜像,项目 30
Btw:这种方法不要滥用得好,锻炼能力为妙。
以上方法总结网上的一些前辈的经验,对普通壳足够了。
至于对Themida ,Acprotect,Asprotect等各版本强壳,有防调试(推荐用硬件断点),就算找到OEP,也要处理stolen code,自校验,重整输入表等等工作,,难度蛮大的,要不断深入自学
4.按一下F9运行程序,直接来到了跳转处,按下F8,到达程序OEP。
方法三:内存镜像法
1:用OD打开软件!
2:点击选项——调试选项——异常,把里面的忽略全部√上!CTRL+F2重载下程序!
3:按ALT+M,打开内存镜象,找到程序的第一个.rsrc.按F2下断点,然后按SHIFT+F9运行到断点,接着再按ALT+M,打开内存镜象,找到程序的第一个.rsrc.上面的.CODE(也就是00401000处),按F2下断点!然后按SHIFT+F9(或者是在没异常情况下按F9),直接到达程序OEP!
Dump文件分析(转发)

Dump⽂件分析(转发)原⽂:本⽂主要介绍Dump⽂件结构,理解Dump⽂件对于分析线程⾼占⽤、死锁、内存溢出等⾼级问题有⾮常重要的指导意义。
什么是Dump⽂件Dump⽂件是进程的内存镜像。
可以把程序的执⾏状态通过调试器保存到dump⽂件中。
Dump⽂件是⽤来给程序编写⼈员调试程序⽤的,这种⽂件必须⽤专⽤⼯具软件打开。
如何⽣成Dump⽂件使⽤命令:jstack pid可以查看到当前运⾏的java进程的dump信息。
Dump⽂件结构⾸先浏览⼀下dump⽂件的⽂本内容:Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.77-b03 mixed mode):"Attach Listener" #37 daemon prio=9 os_prio=0 tid=0x00007f87b42b7000 nid=0x680f waiting on condition [0x0000000000000000]ng.Thread.State: RUNNABLE"Druid-ConnectionPool-Destory-331358539" #36 daemon prio=5 os_prio=0 tid=0x00007f87a4278800 nid=0x67e4 waiting on condition [0x00007f87b8dce000] ng.Thread.State: TIMED_WAITING (sleeping)at ng.Thread.sleep(Native Method)at com.alibaba.druid.pool.DruidDataSource$DestroyConnectionThread.run(DruidDataSource.java:1724)"Druid-ConnectionPool-Create-331358539" #35 daemon prio=5 os_prio=0 tid=0x00007f87a4022000 nid=0x67e3 waiting on condition [0x00007f87ce86a000] ng.Thread.State: WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for <0x00000000b3804848> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:1629)"Abandoned connection cleanup thread" #31 daemon prio=5 os_prio=0 tid=0x00007f87e0d91800 nid=0x672b in Object.wait() [0x00007f87cd2c2000]ng.Thread.State: TIMED_WAITING (on object monitor)at ng.Object.wait(Native Method)at ng.ref.ReferenceQueue.remove(ReferenceQueue.java:143)- locked <0x00000000b422d1e8> (a ng.ref.ReferenceQueue$Lock)at com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:43)"DestroyJavaVM" #30 prio=5 os_prio=0 tid=0x00007f87e0008800 nid=0x670b waiting on condition [0x0000000000000000]ng.Thread.State: RUNNABLE"http-nio-8081-AsyncTimeout" #28 daemon prio=5 os_prio=0 tid=0x00007f87e016e800 nid=0x6727 waiting on condition [0x00007f87b94cf000]ng.Thread.State: TIMED_WAITING (sleeping)at ng.Thread.sleep(Native Method)at org.apache.coyote.AbstractProtocol$AsyncTimeout.run(AbstractProtocol.java:1211)at ng.Thread.run(Thread.java:745)"http-nio-8081-Acceptor-0" #27 daemon prio=5 os_prio=0 tid=0x00007f87e0166000 nid=0x6726 runnable [0x00007f87b95d0000]ng.Thread.State: RUNNABLEat sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:422)at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250)- locked <0x00000000b410d480> (a ng.Object)at .NioEndpoint$Acceptor.run(NioEndpoint.java:455)at ng.Thread.run(Thread.java:745)"http-nio-8081-ClientPoller-0" #26 daemon prio=5 os_prio=0 tid=0x00007f87e0292800 nid=0x6725 runnable [0x00007f87b96d1000]ng.Thread.State: RUNNABLEat sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)- locked <0x00000000b410d6c0> (a sun.nio.ch.Util$2)- locked <0x00000000b410d6b0> (a java.util.Collections$UnmodifiableSet)- locked <0x00000000b410d668> (a sun.nio.ch.EPollSelectorImpl)at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)at .NioEndpoint$Poller.run(NioEndpoint.java:793)at ng.Thread.run(Thread.java:745)"http-nio-8081-exec-10" #25 daemon prio=5 os_prio=0 tid=0x00007f87e028c000 nid=0x6724 waiting on condition [0x00007f87b97d2000]ng.Thread.State: WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for <0x00000000b410d898> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)at ng.Thread.run(Thread.java:745)其中每个空⾏⽤于分隔⼀个线程,每个线程的信息是以堆栈信息的⽅式展开,显⽰了⽬前正在调⽤的⽅法以及所在的代码⾏。
Armadillo脱壳知识和方法大全

般情况下,这个跳转比较大的话,就改为jmp,而跳转比较小的话,就改nop)。[注:下此断点的目的是找到Magic Jump,修改Magic Jump目的
是避开的IAT的加密。]
2、找OEP
下断点bp GetCurrentThreadId/bp CreateThread,shift+f9运行,中断后,取消断点,Alt+F9返回,单步执行,看到一个call edi之类的。F7
进入,即到oep。OD不要关!打开import--选择进程--OEP输入va--自动搜索IAT--获取输入表--显示无效函数--CUT!
(二) 双线程的标准壳
总体步骤:1、要双变单;2、处理IAT,修改Magic Jump;3、寻找OEP;4、修复
1、双变单,方法有三。
方法一:PATCH代码法
004010109D popfd
0040101161 popad
00401012- E9 8F9FA777jmp KERNEL32.OpenMutexA
点右键选择重建eip,f9运行,断下后,取消断点, ctrl+g到00401000,恢复修改。
方法二:下断点BP OpenMutexA,SHIFT+F9运行,断下后,ALT+F9返回,返回后,将返回代码下面的第一个跳转改为相反跳转,再次SHIFT+F9
,断下后,ALT+F9返回,再次将返回代码下面的第一个跳转改为相反跳转。然后再一次SHIFT+F9,取消断点,至此,同样,双进程转单进程完毕!
此法相对简单,另外适用于00401000空数据不能修改的程序。
(2)修改Magic Jump 。
下断BP GetModuleHandleA+5,运行,一般是在堆栈窗口出现ASCII "kernel32.dll"和ASCII "VirtualFree后,再运行一次,就是返回时机,中
浅谈壳的加载步骤及手动脱壳

浅谈壳的加载步骤及手动脱壳。
现在玩脱壳的人越来越多了,不知道是好事还是坏事。
现在玩手动脱壳一般三样工具足矣:loader,ImpREC,TRW2000。
也许是这三剑客的功能太强大,因此手动脱壳也变得象流水化作业。
大致以下几个步骤就搞定了。
1)loader找OEP.(OEP就是程序原来的入口点,即Original Entry Point)2)TRW2000来Dump。
也就是把内存映象保存为文件。
3)ImpREC修补Import Table.(也就是修补程序原来的API地址)不过如果这样,那么我想手动脱壳也没有必要了,因为更先进的工具如各种脱壳机会更快捷有效。
既然是手动脱壳,当然想对壳有所了解,那么让我们看看壳是如何工作的吧。
壳和病毒从某些方面比较类似,都需要比原程序代码更早的获得控制权,这是通过在原程序的代码执行前加入自己的一段代码来实现的。
注意我说的这是执行时的情况。
对于文件中的情况,就是壳修改了原程序的执行文件的组织结构,从而达到壳的代码能够比原程序的代码提前获得控制权,并且不会影响原程序的正常运行,所以从这点上说,壳和病毒很类似。
现在的执行文件一般都是PE格式,如果你对PE格式一无所知,最好还是去看一看相关的资料。
我没有那么地道的专业知识,也怕误人子弟。
相关名词1)Entry Point (入口点)PE格式的可执行文件的执行时的入口点,即是PE格式中的Entry Point。
用PEditor或者LordPE之类的PE查看工具看看NotePad.exe,你就会看到Entry Point的值。
也就是说NotePad.exe在执行时的第一行代码的地址应该就是这个值。
(当然应该加上基地址)2)Section (节区)PE格式文件是按节区进行规划组织的,不同的节区一般保存的数据的作用也不相同。
通常使用缺省方式编译的程序文件,有CODE/DATA/TLS/.text/.data/.tls/.rsrc/.rdata/.edata/.reloc等不同的名称,有的用于保存程序代码,如CODE和.text节区,有的用于保存程序中的变量的,如DATA/.data节区,有的保存重定位信息,如.reloc,有的用于保存资源数据,如.rsrc。
脱壳经验谈菜鸟入门必备知识

至于GetModuleHandle.函数在壳运行过程的重要性也是很容易理解的。壳在解码代码和数据过程中,光靠它自身输入表中的函数是绝对不够的,壳需要动态加载一些dll文件并获得相应的函数地址。当填写IAT时,有些dll其实已经加载过了,这个时候就需要GetModuleHandle.获取这些dll的句柄,再通过GetProcAddress获得函数地址。
VirtualAlloc,VirtualFree和VirtualProtect这三个函数在壳运行过程中有两个用途:
一是申请虚拟内存放代码或IAT。有些壳会把解密代码的一部分放在自己申请的内存地址中,这样即使脱壳了,由于缺少代码也不能运行,像穿山甲的Code Splicing功能以及ASPR中让人抓狂的补区段都是要通过这些函数来完成的。VirtualProtect是用来修改内存属性的,作用是修改区段属性,然后向内存中写入解码后的数据;某些壳HookAPI的时候也会使用这个函数来修改系统dll的属性,以便修改系统dll,达到Hook的目的。
BOOL VirtualProtect(
PVOID pvAddress,
DWORD dwSize,
DWORD flNewProtect,
PDWORD pflOldProtect
);
是不是有点儿晕呢?没关系,先放一下,了解一下别的东西后再回过头来看这些,因为下面的内容需要这些函数的知识,等介绍后面的知识之后再进一步讨论。
一个加壳程序,会对程序的代码,数据,资源,输入表等进行处理,然后再把程序入口点指向壳的代码,并重新为壳自身建立一个输入表---这一点是很重要的。随便打开加过壳的程序,我们可以看到程序输入表中调用的函数少的可怜,但是,对比过几个程序后,我们会发现一些规律,即这些壳一般都会引用某些特定的API,这些就是这里要讲的-----几个同壳密切相关的API函数。
lordpe 使用

lordpe 使用
LordPE是一款能够抓取内存映像的用来脱壳的软件,它能够把一个进程的内存数据给Dump下来,然后保存为文件。
使用LordPE的一般步骤如下:
1. 打开LordPE软件。
注意要用管理员权限打开,不然可能看不到正在被OD调试的进程。
2. 用LordPE查看了将要用到的一些PE信息,这些信息包括PE文件的入口RVA、映像地址和代码节的相关数据。
3. 用C32ASM对代码节进行加密。
具体操作是用C32ASM以十六进制的方式打开可执行文件,然后从代码节的文件偏移开始选择,一直选到相应位置。
之后单击右键,在弹出的快捷菜单上选择“修改数据”命令,在“修改数据”对话框中选择“异或”算法来对代码节进行加密。
4. 保存以后使用在前面章节编写的添加节表的软件对可执行文件添加一个新的节。
在新节中写入了还原代码节的解密指令。
5. 用LordPE修改该可执行文件的入口地址、代码节属性和新添加节的属性。
6. 最后运行修改过的可执行文件,检查是否能正常运行。
如需获取更多关于LordPE使用的信息,建议查阅计算机书籍或咨询专业技术人员。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
外壳程序解压还原后就会跳到OEP处执行,此时内存映像文件是己解压的程序。
这时就可抓取内存映像文件了(该过程称为Dump)。
当然不一定非要在程序原入口点抓取,只要能保证内存映像文件是己还原的就行了。
继续上一个实例notepad.upx.exe,到OEP后就可以Dump取内存映像文件:
004010CC55push ebp
004010CD8BEC mov ebp,esp
004010CF83EC44sub esp,44
运行LordPE.EXE,点击Options,默认选项如下:
默认选上“Fulldump:pasteheaderfromdisk”,PE头的信息直接从磁盘文件获得。
设置好后,在LordPE的进程窗口选择notepad.upx.exe,点击右键,执行“dumpfull”菜单命令。
如图:
将内存抓取的文件另存为dumped.exe,此时程序还不能运行,接下来就是重建输入表。