UPX壳

使用upX压缩之后对比入下

现在使用OD脱压缩壳

注意配置OD的UDD路径,还有异常选项别忘设置

然后用OD在入我们前面加壳的程序。断在0x01014240

然而原来的入口

0100739D     0000                               add byte ptr ds:[eax],al
0100739F     0000                               add byte ptr ds:[eax],al
010073A1     0000                               add byte ptr ds:[eax],al
010073A3     0000                               add byte ptr ds:[eax],al
010073A5     0000                               add byte ptr ds:[eax],al
010073A7     0000                               add byte ptr ds:[eax],al
010073A9     0000                               add byte ptr ds:[eax],al
010073AB     0000                               add byte ptr ds:[eax],al
010073AD     0000                               add byte ptr ds:[eax],al
010073AF     0000                               add byte ptr ds:[eax],al
010073B1     0000                               add byte ptr ds:[eax],al
010073B3     0000                               add byte ptr ds:[eax],al
010073B5     0000                               add byte ptr ds:[eax],al
010073B7     0000                               add byte ptr ds:[eax],al

被改成了00,说明被移走了。下面就是脱壳修复。就是在适当时机,当原始信息还原的时候,把他dump出来,然后在修复一些东西,让其变成脱壳了并且正常运行的程序。总体来说流程是

1. F9运行程序, F12暂停
2. 根据堆栈调用链回溯main函数,main函数的上面就是程序的入口点.
   alt+k查看堆栈调用, 选择最后一个show call, 往上翻,找vc7.0的入口汇编push 70
   在push 70处下一个硬件执行断点. 为什么要下硬件执行断点?

3. 重载程序(ctrl+f2), F9运行程序 此时中断到oep处.  debug---> hardware breakpoints 删除
4. loadpe dump程序
5. importrec修复导入表

我们可以根据esp定律,使用插件,IDAFicator,在执行完pushad操作之后,对esp下硬件断点,全速运行当再断下来时候就是popad操作,即将到达原始程序oep。,此时

010143BD     61                                 popad
010143BE     8D4424 80                          lea eax,dword ptr ss:[esp-80]
010143C2     6A 00                              push 0
010143C4     39C4                               cmp esp,eax
010143C6   ^ 75 FA                              jnz short notepad.010143C2
010143C8     83EC 80                            sub esp,-80
010143CB   - E9 CD2FFFFF                        jmp notepad.0100739D

此时sub esp,-80

然后观察0100739D跳过去代码特征。发现这里739D是入口点。

0100739D     6A 70                              push 70
0100739F     68 98180001                        push notepad.01001898
010073A4     E8 BF010000                        call notepad.01007568
010073A9     33DB                               xor ebx,ebx
010073AB     53                                 push ebx
010073AC     8B3D CC100001                      mov edi,dword ptr ds:[10010CC]                   ; kernel32.GetModuleHandleA
010073B2     FFD7                               call edi
010073B4     66:8138 4D5A                       cmp word ptr ds:[eax],5A4D
010073B9     75 1F                              jnz short notepad.010073DA
010073BB     8B48 3C                            mov ecx,dword ptr ds:[eax+3C]
010073BE     03C8                               add ecx,eax

看到GetModuleHandleA,然后的步骤就是从内存dump出来。

然后就是修复oep,现在程序入口点739D,用loadPE修复,然后修复程序的导入表比如ThunkValue是个虚拟内存要修改成原来的。使用ImportREC,进入ImprotREC选择我们脱壳的程序。

先填写正确的OEP然后点自动搜索IAT,提示导入表RVA是1000,我们去OD看看是不是

01001000  77DA6FEF  advapi32.RegQueryValueExW
01001004  77DA6C17  advapi32.RegCloseKey
01001008  77DCBA25  advapi32.RegCreateKeyW
0100100C  77DCBD05  advapi32.IsTextUnicode
01001010  77DA7AAB  advapi32.RegQueryValueExA
01001014  77DA7842  advapi32.RegOpenKeyExA
01001018  77DAD757  advapi32.RegSetValueExW
0100101C  00000000
01001020  7718D270  comctl32.CreateStatusWindowW
01001024  00000000
01001028  77F0DC19  gdi32.EndPage
0100102C  77F24A05  gdi32.AbortDoc
01001030  77F0DEA9  gdi32.EndDoc
01001034  77EF6E5F  gdi32.DeleteDC
01001038  77F0F456  gdi32.StartPage
0100103C  77EF7F9D  gdi32.GetTextExtentPoint32W
01001040  77EFBE28  gdi32.CreateDCW
01001044  77F24B25  gdi32.SetAbortProc
01001048  77EFA5BB  gdi32.GetTextFaceW
0100104C  77EF7EAC  gdi32.TextOutW
01001050  77F25695  gdi32.StartDocW
01001054  77F1FB22  gdi32.EnumFontsW
01001058  77EF61C1  gdi32.GetStockObject

发现就是导入表。大小是348,然后修改ImportREC里导入表rva和大小。点击获取导入表。然后点击修复转储到我们刚才脱壳dump出的文件里。这时候就能正常运行脱壳的程序了。

前面是一种方法,是我们知道原来OEP位置,但是如果我们不确定加壳程序有什么信息,采用下面这种方法。就是我们想让程序跑起来然后回溯,比如在运行时点击暂停,然后观察调用栈情况,

找到名字是我们程序的调用最后最下面一层,右键点击showcal。这里就是notepadXXXX,倒数第二个

在往上翻,就找到的OEP了

之所以是这,因为他符合vc7的OEP特征,每种编译器编译的二进制文件都有自己的特征。如果不熟悉oep特征,可以先确定程序是什么编译的。可以通过如file format identififier等工具先查下,然后去搜索这类程序的OEP特征。参考资料

https://blog.csdn.net/youyou519/article/details/82418055

https://blog.csdn.net/cdsntxz158/article/details/7998778

然后我们在oep处下一个硬件执行断点。然后重新运行,全速运行,就断到了OEP了。后面步骤就跟第一个方法一样了,通过lordpe等工具把程序从内存dump出来,修复OEP,重建导入表。

另一个demo

下面看一个稍微复杂点的带反调试的UPX壳。

上图是用这种加壳软件加壳前和加壳后的对比。

并且运行起来加壳程序可以在任务管理器看到这个程序是双进程(猜测是双进程守护类型)。下面分析一下壳的流程。

先单步走到

0101D10C     E8 00000000                        call notepad_.0101D111
0101D111     5D                                 pop ebp
0101D112     81ED 8E290200                      sub ebp,2298E
0101D118     B9 02120000                        mov ecx,1202
0101D11D     8DBD D6290200                      lea edi,dword ptr ss:[ebp+229D6]
0101D123     8BF7                               mov esi,edi
0101D125     AC                                 lods byte ptr ds:[esi]
0101D126     F9                                 stc
0101D127     EB 01                              jmp short notepad_.0101D12A

这里发现走过nop到达上面0101D10C这里,执行了一条call下一条指令的地址,下一条pop ebp,因为call等于push eip,jmpxxx,他这里紧接着pop ebp,相当于mov ebp eip,然后ebp减去2298E,然后后续一些了操作在操作eax直到

0101D156     AA                                 stos byte ptr es:[edi]
0101D157   ^ E2 CC                              loopd short notepad_.0101D125

算出的值又给回了edi地址里。然后下面进入一个循环,fellow进去看一下

0101D125     AC                                 lods byte ptr ds:[esi]
0101D126     F9                                 stc
0101D127     EB 01                              jmp short notepad_.0101D12A
0101D129     E8 34B9FEC8                        call CA008A62
0101D12E     C0C0 8D                            rol al,8D
0101D131     FEC8                               dec al
0101D133     EB 01                              jmp short notepad_.0101D136

发现这循环又回到了之前取esi地址的地方。 在观察此时ecx为1202即循环次数。我们让他跳过循环直接运行到循环结束的地方也就是loopd的下一条指令,此时就已经循环解码完成

如图,od显示这里是moduleEntryPoint,接下来指令,把ebp+2289DD地址的值给eax,ecx赋值573然后call一个地方,进去看

0101DC4A     8BF8                               mov edi,eax
0101DC4C     33C0                               xor eax,eax
0101DC4E     33DB                               xor ebx,ebx
0101DC50     33D2                               xor edx,edx
0101DC52     8A07                               mov al,byte ptr ds:[edi]
0101DC54     F7E2                               mul edx
0101DC56     03D8                               add ebx,eax
0101DC58     42                                 inc edx
0101DC59     47                                 inc edi
0101DC5A   ^ E2 F6                              loopd short notepad_.0101DC52
0101DC5C     93                                 xchg eax,ebx
0101DC5D     C3                                 retn

在把eax给了edi之后,然后对eax做了一些了移动相乘之类的操作,把ebx给了eax,所以我们f4直接跑到这里循环结束010dc5c处。然后f7,执行完这个call,回到调用模块,

此时eax为0002079D,

将其放入这里的[0101dc6e]放入dump

再往下走

0101D16F     8B85 DB340200                      mov eax,dword ptr ss:[ebp+234DB]
0101D175     0340 3C                            add eax,dword ptr ds:[eax+3C]

这些执行完0101D16F后eax为010000000,在模块里发现这就是base基址即Dos头,所以下面取eax+3C地址里的值,这些就知道在操作pe结构的东西了。[eax+3C],如果不熟悉PE结构,可以通过od自带功能,在模块列表,找到你要查询的基址那里点右键选dump,即可看到这个结构体。如下图

发现这里就是PE头的偏移。里面是E0,然后eax+e0,发现e0偏移即是PE头了。然后下面一条汇编指令是再加80,继续观察

发现80即使导入表的rva了。 然后单步走发现把其家属基址给ecx即导入表真正地址。然后单步去除导入表0x10里的值,10D035

然后加基址

0101D190     8B18                               mov ebx,dword ptr ds:[eax]                       ; kernel32.LoadLibraryA

发现是找

LoadLibraryA,估计是要导入自己的dll。继续往下

0101D198     F785 E3340200 01000000             test dword ptr ss:[ebp+234E3],1
0101D1A2     74 09                              je short notepad_.0101D1AD
0101D1A4     803B CC                            cmp byte ptr ds:[ebx],0CC
0101D1A7     0F84 F4090000                      je notepad_.0101DBA1

我们看到判断刚才那你是不是1,是的话跳转到一个地址,不是道haul继续往下判断,ebx地址的值是不是CC,即看看是不是被下了软件断点。所以我们推出je跳过去的代码就是反调试用的。

0101DBA1     6A 00                              push 0
0101DBA3     6A FF                              push -1
0101DBA5     FF95 393A0200                      call dword ptr ss:[ebp+23A39]

再看下ebp+23A39

0101E1BC     0000                               add byte ptr ds:[eax],al
0101E1BE     0000                               add byte ptr ds:[eax],al

发现过去opcode是0000,过去就蹦了。所以不再去关调试这条线路了,回到代码,

0101D1AD     83C0 04                            add eax,4
0101D1B0     8B18                               mov ebx,dword ptr ds:[eax]                       ; kernel32.GetProcAddress
0101D1B2     899D B7360200                      mov dword ptr ss:[ebp+236B7],ebx
0101D1B8     F785 E3340200 01000000             test dword ptr ss:[ebp+234E3],1
0101D1C2     74 09                              je short notepad_.0101D1CD
0101D1C4     803B CC                            cmp byte ptr ds:[ebx],0CC
0101D1C7     0F84 D4090000                      je notepad_.0101DBA1

发现有时再操作另一个函数GetProcAddress,继续

0101D1CD     8D85 1C3A0200                      lea eax,dword ptr ss:[ebp+23A1C]
0101D1D3     50                                 push eax
0101D1D4     FF95 B3360200                      call dword ptr ss:[ebp+236B3]
0101D1DA     8BF0                               mov esi,eax                                      ; ntdll.7C920000
0101D1DC     8D85 263A0200                      lea eax,dword ptr ss:[ebp+23A26]

发现push的是ntdll.dll,,call的是LoadlibraryA。再把加载这个dll的地址给esi,然后单步发现把诸如NtTerminateProcess这类字符给eax,给eax,然后还是用了参数,getProcessAddress,然后call一个函数,很明显是过度函数地址的作用。进去给他右键个label,GetAPI方便观察。,然后后面一系列的初始化函数,单步走到这段结束。此时壳的函数初始化完了。

0101D37B     8985 CE3B0200                      mov dword ptr ss:[ebp+23BCE],eax                 ; kernel32.GetCommandLineA
0101D381     8BFD                               mov edi,ebp
0101D383     8D85 622F0200                      lea eax,dword ptr ss:[ebp+22F62]
0101D389     50                                 push eax
0101D38A     64:FF35 00000000                   push dword ptr fs:[0]
0101D391     64:8925 00000000                   mov dword ptr fs:[0],esp
0101D398     8BBD DB340200                      mov edi,dword ptr ss:[ebp+234DB]
0101D39E     037F 3C                            add edi,dword ptr ds:[edi+3C]

单步下去发现获得控制台参数,然后把一个貌似是oep地址的值给eax,

0101D38A     64:FF35 00000000                   push dword ptr fs:[0]
0101D391     64:8925 00000000                   mov dword ptr fs:[0],esp
0101D398     8BBD DB340200                      mov edi,dword ptr ss:[ebp+234DB]
0101D39E     037F 3C                            add edi,dword ptr ds:[edi+3C]
0101D3A1     8BB5 DB340200                      mov esi,dword ptr ss:[ebp+234DB]
0101D3A7     8B4F 54                            mov ecx,dword ptr ds:[edi+54]
0101D3AA     8D85 F43B0200                      lea eax,dword ptr ss:[ebp+23BF4]
0101D3B0     50                                 push eax
0101D3B1     6A 04                              push 4
0101D3B3     51                                 push ecx
0101D3B4     FFB5 DB340200                      push dword ptr ss:[ebp+234DB]
0101D3BA     6A FF                              push -1
0101D3BC     FF95 C63A0200                      call dword ptr ss:[ebp+23AC6]

发现还是在遍历PE结构,去sizeofHeader,然后继续单步发现把sizeofHeader当中菜蔬,又放进去基址之类的call一个函数

0101D3A7     8B4F 54                            mov ecx,dword ptr ds:[edi+54]                    ; sizeofHeader
0101D3AA     8D85 F43B0200                      lea eax,dword ptr ss:[ebp+23BF4]
0101D3B0     50                                 push eax
0101D3B1     6A 04                              push 4
0101D3B3     51                                 push ecx
0101D3B4     FFB5 DB340200                      push dword ptr ss:[ebp+234DB]                    ; base
0101D3BA     6A FF                              push -1
0101D3BC     FF95 C63A0200                      call dword ptr ss:[ebp+23AC6]                    ; kernel32.VirtualProtectEx

VirtualProtectEx函数可以改变在特定进程中内存区域的保护属性。

0006FFA4   0101D3C2  /CALL to VirtualProtectEx from notepad_.0101D3BC
0006FFA8   FFFFFFFF  |hProcess = FFFFFFFF
0006FFAC   01000000  |Address = notepad_.01000000
0006FFB0   00001000  |Size = 1000 (4096.)
0006FFB4   00000004  |NewProtect = PAGE_READWRITE
0006FFB8   0101E377  \pOldProtect = notepad_.0101E377
0006FFBC   0006FFE0  Pointer to next SEH record
0006FFC0   0101D6E5  SE handler
0006FFC4   7C817067  RETURN to kernel32.7C817067

发现这个函数参数要改成可读可写,然后接着单步进去看下一个Call,发现进去首先是GetModuleFileNameA,获取模块名。

0101D726     DBAD C3370200                      fld tbyte ptr ss:[ebp+237C3]
0101D72C     0F31                               rdtsc

发现获取的就是我们调试的进程。然后单步几部发现如上,浮点操作取值。将这个地址的浮点数压栈,接着rdtsc指令是得到CPU自启动以后的运行周期,然后单步比较ah是否为0,等于0跳一个地方,先不管,紧接着单步发现call ZwSetInformaticaThread,进去看一下参数

ZwSetInformationThread
ZwSetInformationThread拥有两个参数,第一个参数用来接收当前线程的句柄,第二个参数表示线程信息类型,若其值设置为ThreadHideFromDebugger(0x11),使用语句ZwSetInformationThread(GetCurrentThread(), ThreadHideFromDebugger, NULL, 0);调用该函数后,调试进程就会被分离出来。该函数不会对正常运行的程序产生任何影响,但若运行的是调试器程序,因为该函数隐藏了当前线程,调试器无法再收到该线程的调试事件,最终停止调试。还有一个函数DebugActiveProcessStop用来分离调试器和被调试进程,从而停止调试。两个API容易混淆,需要牢记它们的区别。

所以这里是调用这个函数是用来进行反调试的。所以需要STRONGOD把KernMode模块打开,防止此类反调试。不然就会被停止调试。

0101D73F     FF95 763A0200                      call dword ptr ss:[ebp+23A76]                    ; SetInformationThread
0101D745     FF95 8A3A0200                      call dword ptr ss:[ebp+23A8A]                    ; ntdll.CsrGetProcessId一般程序正常启动时是不具备调试权限(SedebugPrivilege)的,除非自己有提权的需要主动开启,但是调试器启动程序的时候,由于调试器本身会开启调试权限,所以被调试进程会继承调试权限,因此我们可以通过检查进程是否具有调试权限来进行反调试。
检查进程是否具有调试权限的方式很简单,系统启动的时候会启动一个核心进程csrss.exe,我们可以通过判断能否使用OpenProcess打开该进程来检查当前进程是否具有调试权限,因为只有拥有管理员权限+调试权限的进程才能打开csrss.exe的句柄。严格来说这种检查方法是不太严格的,因为当进程有调试权限无管理员权限的时候也不能打开csrss.exe的句柄,幸运的是,大多数调试器都会要求提供管理员权限,所以被调试程序也会同时拥有管理员权限+调试权限。
通过CsrGetProcessId函数可以获取csrss.exe的PID,然后通过OpenProcess尝试打开csrss.exe的句柄:

紧接着获取当前进程PID,单步几部然后发现打开这个进程。这个进程是csrss,如果debug权限是可以打开的,打开成功返回PID是不等于0,所以这里不等于0,就会跳转到停止的地方去了,这里相当的原因是StrongOD已经帮我们操作了。

继续往下跟,发现有关于比如填充800001这种异常的数据。接着往下又是VirtualAlloc申请内存。申请了内存,又修改了内存属性,调用esi

0101D7B4     50                                 push eax
0101D7B5     6A FF                              push -1
0101D7B7     FF95 C63A0200                      call dword ptr ss:[ebp+23AC6]
0101D7BD     FFD6                               call esi

这种情况正常状态,会触发异常,调试状态不会触发。如果跑过了,已经触发异常,就单步走走到调用异常的,慢慢比如在每层导数第一个函数下断然后一步一步跑发现走到

7C9232A6     FFD1                               call ecx                                         ; notepad_.0101D679
7C9232A8     64:8B25 00000000                   mov esp,dword ptr fs:[0]

如上面,call,ecx,ecx是源程序模块的地址不再是ntdll的了,所以这里就是一个异常的出口。

0101D679     55                                 push ebp
0101D67A     8BEC                               mov ebp,esp
0101D67C     57                                 push edi
0101D67D     8B45 10                            mov eax,dword ptr ss:[ebp+10]
0101D680     8B5D 08                            mov ebx,dword ptr ss:[ebp+8]
0101D683     8B1B                               mov ebx,dword ptr ds:[ebx]
0101D685     8BB8 9C000000                      mov edi,dword ptr ds:[eax+9C]
0101D68B     3B9F 5B360200                      cmp ebx,dword ptr ds:[edi+2365B]
0101D691     74 0B                              je short notepad_.0101D69E
0101D693     8BA8 9C000000                      mov ebp,dword ptr ds:[eax+9C]
0101D699     E9 AE040000                        jmp notepad_.0101DB4C
0101D69E     F787 E3340200 04000000             test dword ptr ds:[edi+234E3],4
0101D6A8     74 17                              je short notepad_.0101D6C1
0101D6AA     8B58 04                            mov ebx,dword ptr ds:[eax+4]
0101D6AD     0358 08                            add ebx,dword ptr ds:[eax+8]
0101D6B0     0358 0C                            add ebx,dword ptr ds:[eax+C]
0101D6B3     0358 10                            add ebx,dword ptr ds:[eax+10]
0101D6B6     0358 14                            add ebx,dword ptr ds:[eax+14]
0101D6B9     0358 18                            add ebx,dword ptr ds:[eax+18]
0101D6BC     83FB 00                            cmp ebx,0
0101D6BF   ^ 75 D2                              jnz short notepad_.0101D693
0101D6C1     FFB7 57360200                      push dword ptr ds:[edi+23657]
0101D6C7     8F80 B8000000                      pop dword ptr ds:[eax+B8]
0101D6CD     89B8 B4000000                      mov dword ptr ds:[eax+B4],edi
0101D6D3     C780 B0000000 04000000             mov dword ptr ds:[eax+B0],4
0101D6DD     B8 00000000                        mov eax,0
0101D6E2     5F                                 pop edi
0101D6E3     C9                                 leave
0101D6E4     C3                                 retn
0101D6E5     55                                 push ebp
0101D6E6     8BEC                               mov ebp,esp
0101D6E8     8B45 10                            mov eax,dword ptr ss:[ebp+10]
0101D6EB     8BA8 9C000000                      mov ebp,dword ptr ds:[eax+9C]
0101D6F1     E9 4E040000                        jmp notepad_.0101DB44
0101D6F6     E8 00000000                        call notepad_.0101D6FB
0101D6FB     5D                                 pop ebp
0101D6FC     81ED 782F0200                      sub ebp,22F78
0101D702     68 04010000                        push 104
0101D707     8D85 BF360200                      lea eax,dword ptr ss:[ebp+236BF]
0101D70D     50                                 push eax
0101D70E     6A 00                              push 0
0101D710     FF95 DD3A0200                      call dword ptr ss:[ebp+23ADD]
0101D716     F785 E3340200 01000000             test dword ptr ss:[ebp+234E3],1
0101D720     0F84 66010000                      je notepad_.0101D88C
0101D726     DBAD C3370200                      fld tbyte ptr ss:[ebp+237C3]
0101D72C     0F31                               rdtsc
0101D72E     80FC 00                            cmp ah,0
0101D731     0F84 15040000                      je notepad_.0101DB4C
0101D737     6A 00                              push 0
0101D739     6A 00                              push 0
0101D73B     6A 11                              push 11
0101D73D     6A FE                              push -2
0101D73F     FF95 763A0200                      call dword ptr ss:[ebp+23A76]
0101D745     FF95 8A3A0200                      call dword ptr ss:[ebp+23A8A]

回来之后这里就是异常handle做的操作了。 发现就是在填充异常结构体。

然后这里如果是0x80000001就继续不是的话。就退出了。

0101D6AA     8B58 04                            mov ebx,dword ptr ds:[eax+4]                     ; eax context
0101D6AD     0358 08                            add ebx,dword ptr ds:[eax+8]
0101D6B0     0358 0C                            add ebx,dword ptr ds:[eax+C]
0101D6B3     0358 10                            add ebx,dword ptr ds:[eax+10]
0101D6B6     0358 14                            add ebx,dword ptr ds:[eax+14]
0101D6B9     0358 18                            add ebx,dword ptr ds:[eax+18]
0101D6BC     83FB 00                            cmp ebx,0

这里的eax就是下面结构体

typedef struct _CONTEXT
{+000   DWORD ContextFlags;+004   DWORD Dr0;+008   DWORD Dr1;+00C   DWORD Dr2;+010   DWORD Dr3;+014   DWORD Dr6;+018   DWORD Dr7;+01C   FLOATING_SAVE_AREA FloatSave;+08C   DWORD SegGs;+090   DWORD SegFs;+094   DWORD SegEs;+098   DWORD SegDs;+09C   DWORD Edi;+0A0   DWORD Esi;+0A4   DWORD Ebx;+0A8   DWORD Edx;+0AC   DWORD Ecx;+0B0   DWORD Eax;+0B4   DWORD Ebp;+0B8   DWORD Eip;+0BC   DWORD SegCs;+0C0   DWORD EFlags;+0C4   DWORD Esp;+0C8   DWORD SegSs;+0CC   BYTE   ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
} CONTEXT;

所以他这里把几个硬件断点的值加起来跟0比较其实就是检查有无硬件断点,反硬件断点。如果发现不是领就又调到之前推出的地方去了。然后单步接着看。

0101D6BF   ^\75 D2                              jnz short notepad_.0101D693
0101D6C1     FFB7 57360200                      push dword ptr ds:[edi+23657]                    ; exception exit
0101D6C7     8F80 B8000000                      pop dword ptr ds:[eax+B8]                        ; eip
0101D6CD     89B8 B4000000                      mov dword ptr ds:[eax+B4],edi
0101D6D3     C780 B0000000 04000000             mov dword ptr ds:[eax+B0],4
0101D6DD     B8 00000000                        mov eax,0
0101D6E2     5F                                 pop edi
0101D6E3     C9                                 leave
0101D6E4     C3                                 retn

发现push,pop就是把异常出口给eip(0x0101D7C4),下面就是还原EBP。继续单步跟发现调用了ZwContinue然后kifastSystemCall,发现最后就走出了异常,来到了下面,0101D7E8这个就是异常handler。在哪里下个断。

0101D7C4     5E                                 pop esi
0101D7C5     8DB5 57360200                      lea esi,dword ptr ss:[ebp+23657]
0101D7CB     8D85 65300200                      lea eax,dword ptr ss:[ebp+23065]
0101D7D1     8906                               mov dword ptr ds:[esi],eax
0101D7D3     C746 04 04000080                   mov dword ptr ds:[esi+4],80000004
0101D7DA     9C                                 pushfd
0101D7DB     810C24 00010000                    or dword ptr ss:[esp],100

后面发现,记录了0x80000004,这个可以通过DebugOption,exceptionRand看出这里是个单步异常。然后检测单步异常所以我们要全速运行跳过这段,不然会调试失败。

接下来

0101D7F4    /0F85 52030000                      jnz notepad_.0101DB4C
0101D7FA    |8D85 5F360200                      lea eax,dword ptr ss:[ebp+2365F]
0101D800    |50                                 push eax
0101D801    |FF95 903B0200                      call dword ptr ss:[ebp+23B90]                    ; GetStartupInfor anti debugger
0101D807    |8B85 6F360200                      mov eax,dword ptr ss:[ebp+2366F]
0101D80D    |0385 73360200                      add eax,dword ptr ss:[ebp+23673]
0101D813    |0385 7F360200                      add eax,dword ptr ss:[ebp+2367F]
0101D819    |0385 83360200                      add eax,dword ptr ss:[ebp+23683]
0101D81F    |0385 87360200                      add eax,dword ptr ss:[ebp+23687]
0101D825    |0385 77360200                      add eax,dword ptr ss:[ebp+23677]
0101D82B    |0385 7B360200                      add eax,dword ptr ss:[ebp+2367B]
0101D831    |83F8 00                            cmp eax,0
0101D834    |0F85 12030000                      jnz notepad_.0101DB4C

这里又是反调试,所以我们手动改变Z位让他相等不调到退出处。

接着

0101D834    /0F85 12030000                      jnz notepad_.0101DB4C
0101D83A    |16                                 push ss
0101D83B    |17                                 pop ss
0101D83C    |9C                                 pushfd
0101D83D    |58                                 pop eax
0101D83E    |25 00010000                        and eax,100
0101D843    |3D 00010000                        cmp eax,100
0101D848    |0F84 FE020000                      je notepad_.0101DB4C
0101D84E    |8D85 A3360200                      lea eax,dword ptr ss:[ebp+236A3]

又是个单步反调试,所以我们继续把判断相等的位置改成不跳转。然后继续向下分析。

0101D871     FF95 BA3B0200                      call dword ptr ss:[ebp+23BBA]                    ; kernel32.CreateProcessA

这里就是创建双进程守护了。

0006FF8C   0101D877  /CALL to CreateProcessA from notepad_.0101D871
0006FF90   0101DE42  |ModuleFileName = "C:\Documents and Settings\Administrator\桌面\notepad.exe.ISP.EXE"
0006FF94   00000000  |CommandLine = NULL
0006FF98   00000000  |pProcessSecurity = NULL
0006FF9C   00000000  |pThreadSecurity = NULL
0006FFA0   00000000  |InheritHandles = FALSE
0006FFA4   00000004  |CreationFlags = CREATE_SUSPENDED
0006FFA8   00000000  |pEnvironment = NULL
0006FFAC   00000000  |CurrentDir = NULL
0006FFB0   0101DDE2  |pStartupInfo = notepad_.0101DDE2
0006FFB4   0101DE26  \pProcessInfo = notepad_.0101DE26

这是创建的参数。继续

0101D87D     FF95 A73B0200                      call dword ptr ss:[ebp+23BA7]                    ; kernel32.DebugActiveProcess

调试进程。继续单步几步发现

0101D8DB     FF95 ED3A0200                      call dword ptr ss:[ebp+23AED]                    ; kernel32.CreateFileA

查看参数就是打开自己。

0101D8E6     FF95 293B0200                      call dword ptr ss:[ebp+23B29]                    ; kernel32.GetFileSize

然后获得文件大小,

0101D8F3     FF95 FD3A0200                      call dword ptr ss:[ebp+23AFD]                    ; kernel32.GlobalAlloc

申请一块内存。然后继续单步发现读文件,

0101D912     E8 33030000                        call notepad_.0101DC4A

然后发现call一个地址,进去看下, 发现是循环在做一些操作文件,然后比对相等不相等。如果不相等就跳到退出那里。

继续单步往下,发现是在判断一些标志位。

0101D9E9     E8 0D020000                        call notepad_.0101DBFB

然后 进去看下

发现是在反一些调试窗口

继续往下发现都是在找一些monitor windows,然后继续往下

0101DA26     64:FF35 30000000                   push dword ptr fs:[30]
0101DA2D     58                                 pop eax
0101DA2E     8B40 0C                            mov eax,dword ptr ds:[eax+C]
0101DA31     8B40 0C                            mov eax,dword ptr ds:[eax+C]
0101DA34     C740 20 00000000                   mov dword ptr ds:[eax+20],0
0101DA3B     F785 E3340200 08000000             test dword ptr ss:[ebp+234E3],8

发现就是在操作PEB,0xC处即InLoadOrderModuleList,然后进行一些校验,继续往下

0101DA52     E8 F3010000                        call notepad_.0101DC4A

发现一个call,参数是壳入口,发现又是在自校验壳,进去看下,自校验,这里不能在结尾下断点因为这样会改变比较程序的值,造成不匹配退出所有只能跟。

然后单步跟发现校验结束回到调用点

0101D3BC     FF95 C63A0200                      call dword ptr ss:[ebp+23AC6]                    ; VitualProtect
0101D3C2     E8 2F030000                        call notepad_.0101D6F6                           ; anti_bugger && self check
0101D3C7     8B85 DB340200                      mov eax,dword ptr ss:[ebp+234DB]
0101D3CD     BB 01000000                        mov ebx,1
0101D3D2     E8 AB060000                        call notepad_.0101DA82

发现传进去PE文件的base和1,然后call,进去看在操作section,循环比较看是不是rsrc,.rsr,就是在判断区段是否被修改。

然后后面一些指令也是在操作判断pe结构,继续往下跟,发现申请一块内存。然后继续往下跟发现又是个不知道的循环赋值。但是发现edi里被存上了kernel32.dll,并且后面继续跟发现有loadlibrary,继续跟

0101D4D6     038D DB340200                      add ecx,dword ptr ss:[ebp+234DB]                 ; notepad_.01000000
0101D4DC     8B56 04                            mov edx,dword ptr ds:[esi+4]
0101D4DF     0395 DB340200                      add edx,dword ptr ss:[ebp+234DB]
0101D4E5     E9 AE000000                        jmp notepad_.0101D598

发现在操作PE结构,寻找一些东西。继续,发现

0101BF30                          4B 45 52 4E 45 4C 33 32          ERNEL32
0101BF40  2E 44 4C 4C 00 41 44 56 41 50 49 33 32 2E 64 6C  .DLL.ADVAPI32.dl
0101BF50  6C 00 43 4F 4D 43 54 4C 33 32 2E 64 6C 6C 00 63  l.COMCTL32.dll.c
0101BF60  6F 6D 64 6C 67 33 32 2E 64 6C 6C 00 47 44 49 33  omdlg32.dll.GDI3
0101BF70  32 2E 64 6C 6C 00 6D 73 76 63 72 74 2E 64 6C 6C  2.dll.msvcrt.dll
0101BF80  00 53 48 45 4C 4C 33 32 2E 64 6C 6C 00 55 53 45  .SHELL32.dll.USE
0101BF90  52 33 32 2E 64 6C 6C 00 57 49 4E 53 50 4F 4F 4C  R32.dll.WINSPOOL
0101BFA0  2E 44 52 56 00 00 4C 6F 61 64 4C 69 62 72 61 72  .DRV..LoadLibrar
0101BFB0  79 41 00 00 47 65 74 50 72 6F 63 41 64 64 72 65  yA..GetProcAddre
0101BFC0  73 73 00 00 56 69 72 74 75 61 6C 50 72 6F 74 65  ss..VirtualProte
0101BFD0  63 74 00 00 56 69 72 74 75 61 6C 41 6C 6C 6F 63  ct..VirtualAlloc
0101BFE0  00 00 56 69 72 74 75 61 6C 46 72 65 65 00 00 00  ..VirtualFree...
0101BFF0  45 78 69 74 50 72 6F 63 65 73 73 00 00 00 52 65  ExitProcess...Re
0101C000  67 43 6C 6F 73 65 4B 65 79 00 00 00 43 72 65     gCloseKey...Cre

发现是在解密一些用到的字符串。继续往下跟,然后又发现在解密一段东西,跟着循环发现是解密代码。如下

0101D5D3     64:A1 18000000                     mov eax,dword ptr fs:[18]
0101D5D9     8B40 24                            mov eax,dword ptr ds:[eax+24]
0101D5DC     50                                 push eax
0101D5DD     6A FF                              push -1
0101D5DF     6A 01                              push 1
0101D5E1     FF95 6C3B0200                      call dword ptr ss:[ebp+23B6C]
0101D5E7     83F8 00                            cmp eax,0
0101D5EA     0F84 54050000                      je notepad_.0101DB44
0101D5F0     8985 BB360200                      mov dword ptr ss:[ebp+236BB],eax
0101D5F6     6A 00                              push 0
0101D5F8     6A 00                              push 0
0101D5FA     6A 00                              push 0
0101D5FC     8D85 E1320200                      lea eax,dword ptr ss:[ebp+232E1]
0101D602     50                                 push eax
0101D603     6A 00                              push 0
0101D605     6A 00                              push 0
0101D607     6A FF                              push -1
0101D609     FF95 533B0200                      call dword ptr ss:[ebp+23B53]
0101D60F     F785 E3340200 00100000             test dword ptr ss:[ebp+234E3],1000
0101D619     74 1C                              je short notepad_.0101D637
0101D61B     6A 00                              push 0
0101D61D     6A 00                              push 0
0101D61F     6A 03                              push 3
0101D621     6A 00                              push 0
0101D623     6A 00                              push 0
0101D625     68 00000080                        push 80000000
0101D62A     8D85 BF360200                      lea eax,dword ptr ss:[ebp+236BF]
0101D630     50                                 push eax
0101D631     FF95 ED3A0200                      call dword ptr ss:[ebp+23AED]
0101D637     61                                 popad
0101D638     50                                 push eax
0101D639     64:FF35 00000000                   push dword ptr fs:[0]
0101D640     64:8925 00000000                   mov dword ptr fs:[0],esp

发现这里在读TEB,读取一些信息,然后openthread,然后

ss:[0101E2D6]=7C8104BC (kernel32.CreateRemoteThread)
创建远程线程。查看一下参数eax也就是线程是什么,发现是前面做的反调试相关的东西。所以我们不能让他创建,所以把栈上回调改成0,不创建。

然后继续单步经过一些列单步到了

0101425F     90                                 nop
01014260     60                                 pushad
01014261     BE 00000101                        mov esi,notepad_.01010000
01014266     8DBE 0010FFFF                      lea edi,dword ptr ds:[esi+FFFF1000]
0101426C     57                                 push edi
0101426D     83CD FF                            or ebp,FFFFFFFF
01014270     EB 10                              jmp short notepad_.01014282
01014272     90                                 nop
01014273     90                                 nop
01014274     90                                 nop
01014275     90                                 nop
01014276     90                                 nop
01014277     90                                 nop
01014278     8A06                               mov al,byte ptr ds:[esi]
0101427A     46                                 inc esi
0101427B     8807                               mov byte ptr ds:[edi],al
0101427D     47                                 inc edi
0101427E     01DB                               add ebx,ebx
01014280     75 07                              jnz short notepad_.01014289
01014282     8B1E                               mov ebx,dword ptr ds:[esi]
01014284     83EE FC                            sub esi,-4
01014287     11DB                               adc ebx,ebx
01014289   ^ 72 ED                              jb short notepad_.01014278
0101428B     B8 01000000                        mov eax,1
01014290     01DB                               add ebx,ebx
01014292     75 07                              jnz short notepad_.0101429B
01014294     8B1E                               mov ebx,dword ptr ds:[esi]
01014296     83EE FC                            sub esi,-4

发现就是又加了层UPX壳,然后这个下面的位置下个断点。

然后全速运行就脱壳完了,然后dump发现不能dump,

然后里面有反dump,

antidump
push fs:[30h]
pop eax
MOV EAX,[EAX+0Ch]
MOV EAX,[EAX+0Ch]
MOV DWORD PTR [EAX+20h],0;修改内存镜像大小为0

我们就要把镜像大小修复了,lordPE可以修复。然后dump就成功了。然后修复impactREC就好了。

ASP壳

我们可以观察下加壳之后的程序OEP也变了,并且节也多了两个。脱壳方式跟upx一样。

加密壳

前面步骤跟上面一样,在重建导入表时候发现

发现导入表值是无效的,然后随便打开个看到地址1D0C8过去看看。

这里本来应该是系统函数地址,这里显然不是,被加密了,过去看下填充的地址是什么

这里发现从eax取出真正的函数地址, 然后做了加密跳转过去。这时候需要写个脚本自动把这里的函数地址替换回去。

注意观察加密片段如下

0038001F     8105 3A003800 B9C1F260             add dword ptr ds:[38003A],60F2C1B9
00380029     A1 3A003800                        mov eax,dword ptr ds:[38003A]
0038002E     812D 3A003800 B9C1F260             sub dword ptr ds:[38003A],60F2C1B9
00380038     FFE0                               jmp eax

我们就是要取得eax里面是真正函数地址,所以在这里处理时候可以用sti,sti,两个跳过,sti就是F7的意思,单步两部此时eax就是函数地址,此外根据ImportREC或者OD里观察,iAT起始地址是0x0041D0C4结束地址是0x0041D13C,所以修复的就是这两块直间的值,此外这个程序oep是0x00401000

根据程序修复iat脚本如下

//1.找到oep
//2.找到api数组首地址和end地址
//3.还原地址var oep
var esp_addr
var iat_start
var iat_end
var tmp1
var tmp2
//到达OEPmov iat_start,0041D0C4
mov iat_end,0041D13C
mov oep,00401000bphws oep,"x"
//清理断点
esto
bc
bpmc
bphwc
mov oep,eip
mov esp_addr,espmov tmp2,iat_start//下面是修复代码,就是一个一个取导入表里面的值然后修复
label_loop:cmp tmp2,iat_end
je label_exit
add tmp2,4
mov tmp1,[tmp2]cmp tmp1,0
je label_loopmov eip,tmp1
sti
sti
mov [tmp2],eax
jmp label_loop
label_exit:
mov eip,oep
mov esp,esp_addr
dpe "Unpack.exe",eip
ret

然后run script,就修改好了,

然后用ImportREC修复iat,这时程序就脱壳成功,并且跑起来了,另外脚本编写编码注意gbk,不过我没遇到这种问题。

或者还可以如下,写静态脚本

修复IAT的几种方式:
1.在到达oep之前寻找IAT加密地址跳过,或者找Majec jmp
2.到达oep之后写汇编代码进行修复或者写脚本进行修复

一:在OEP之前进行patch
GetModuleHanldleA+GetProcAddress

1.
shl byte ptr ds:[ecx],cl  //这两句是加密函数名
xor byte ptr ds:[ecx],al
----------------------------------------
2.
mov eax,dword ptr ss:[ebp+4071A6] //这里获取加密地址
这里进行patch的话有两个思路:
   1.把获取加密的地址nop掉
   2.之后肯定会把eax写入一个地址表里,在写入之发再把正确的值进行写入。
    F7往下走就可以看到了mov dword ptr ds:[edi],eax  这里可以进行patch,
    看栈翻一翻会有惊喜!

mov eax,dword ptr ss:[esp-B8]
mov dword ptr ds:[edi],eax
jmp 写入的地址

二:到OEP之后进行Patch
003F0000    B8 C8D04100                     mov eax,41D0C8//iat开始地址
003F0005    8B10                            mov edx,dword ptr ds:[eax]
003F0007    83FA 00                         cmp edx,0
003F000A    74 14                           je 003F0020//判断是否为0
003F000C    8B4A 02                         mov ecx,dword ptr ds:[edx+2]  key指针
003F000F    8B09                            mov ecx,dword ptr ds:[ecx]    取出key1
003F0011    8B52 06                         mov edx,dword ptr ds:[edx+6]  取出key2
003F0014    81FA 00000040                   cmp edx,40000000
003F001A    77 13                           ja 003F002F                  加密方式判断
003F001C    33CA                            xor ecx,edx                  xor加密
003F001E    8908                            mov dword ptr ds:[eax],ecx   保存地址
003F0020    83C0 04                         add eax,4             下一个地址    
003F0023    3D 3CD14100                     cmp eax,41D13C               比较是否是结尾
003F0028  ^ 72 DB                           jb 003F0005
003F002A  - E9 D10FAAFF                     jmp 00401000                 跳到OEP
003F002F    03CA                            add ecx,edx                  AND加密
003F0031  ^ EB EB                           jmp 003F001E
B8C8D041008B1083FA0074148B4A028B098B520681FA00000040771333CA890883C0043D3CD1410072DBE9D10F020003CAEBEB

也可以读取加密地址的代码是xor(8135)还是and(8105)然后进行分支解密

把上面这段脚本代码粘贴到程序空闲的地方,然后把eip拉到这里,相关跳转地址改成自己机器相应的地址即可。

另外还可以在iat表下写断点,看谁给他写的,加密也就在那个附近了。然后把加密nop调,然后写进去真实地址,就达到修复iat的作用了。

再观察一个加密壳样本,发现有pushad,试下esp定律下硬件断点。

0044E214     55                                 push ebp                                         ; oep
0044E215     8BEC                               mov ebp,esp
0044E217     83C4 F0                            add esp,-10
0044E21A     B8 8CE04400                        mov eax,Project1.0044E08C
0044E21F     E8 587EFBFF                        call Project1.0040607C
0044E224     A1 4CFF4400                        mov eax,dword ptr ds:[44FF4C]
0044E229     8B00                               mov eax,dword ptr ds:[eax]
0044E22B     E8 08E6FFFF                        call Project1.0044C838
0044E230     8B0D 28004500                      mov ecx,dword ptr ds:[450028]                    ; Project1.00451B64
0044E236     A1 4CFF4400                        mov eax,dword ptr ds:[44FF4C]
0044E23B     8B00                               mov eax,dword ptr ds:[eax]
0044E23D     8B15 ACDE4400                      mov edx,dword ptr ds:[44DEAC]                    ; Project1.0044DEF8
0044E243     E8 08E6FFFF                        call Project1.0044C850
0044E248     A1 4CFF4400                        mov eax,dword ptr ds:[44FF4C]
0044E24D     8B00                               mov eax,dword ptr ds:[eax]
0044E24F     E8 7CE6FFFF                        call Project1.0044C8D0
0044E254     E8 8F5EFBFF                        call Project1.004040E8

很快找到了oep但是观察下面函数调用,没有显示名称,八成iat是加密的而且,到了oep都没显示,猜测是动态解密。然后先按照流程操作,dump,修复导入表发现导入表又是一堆无效的NO,过去看一下发现如下

00452118  00461624  Project1.00461624
0045211C  004611EC  Project1.004611EC
00452120  0046199C  Project1.0046199C
00452124  00461198  Project1.00461198
00452128  00461354  Project1.00461354
0045212C  00461210  Project1.00461210
00452130  00461B1C  Project1.00461B1C
00452134  00462068  Project1.00462068
00452138  00461B58  Project1.00461B58
0045213C  0046190C  Project1.0046190C
00452140  00461378  Project1.00461378
00452144  0046181C  Project1.0046181C
00452148  00461660  Project1.00461660
0045214C  004618AC  Project1.004618AC
00452150  004613E4  Project1.004613E4
00452154  004618C4  Project1.004618C4
00452158  00461B04  Project1.00461B04
0045215C  00461A08  Project1.00461A08

然后我们去第一个iat位置去看下,把eip拉过去。

然后不停的单步观察,注意看什么时候寄存器或者调用的参数出现真实函数地址,发现如下。

此时去eax找edi数值偏移4的地方取到函数地址,猜测eax处就是真正导入表,所以在dump查看eax,如下,即导入表。

继续单步

009E2846     61                                 popad

此时eax里面是函数真正地址。所以下面操作就是写个脚本根据这些地址和流程修复iat。

根据od和importREC已经刚在跟踪OD的信息知道oep,iat表起始和结尾地址,替换拿到真正iat放在eax时的地址。

脚本跟前面类似,就是就是细节比如,不是单步两次了,是在把真正函数地址eax使用时候下断,也就是在009E2846断下,然后把此时eax(里面存的真正函数地址)写到它对应的iat地址里。注意如果脚本反复跑有异常,那就分段泡脚本,然后把每次考的二进制数据复制到导入表位置,然后dump,修复iat,运行成功。

脚本代码参考。


//1.找到oep
//2.找到api数组首地址和end地址
//3.还原地址var oep
var esp_addr
var iat_start
var iat_end
var tmp1
var tmp2
//下面这个变量记录真正iat的地址
var tmp_bp
//到达OEPmov iat_start,00452118
mov iat_end,000526D8
mov oep,0044E214
mov tmp_bp,009E2846
bphws oep,"x"
//清理断点
esto
bc
bpmc
bphwc
mov oep,eip
mov esp_addr,espmov tmp2,iat_start//下面是修复代码,就是一个一个取导入表里面的值然后修复
label_loop:cmp tmp2,iat_end
je label_exit
add tmp2,4
mov tmp1,[tmp2]cmp tmp1,0
je label_loopmov eip,tmp1bp tmp_bp
esto
bc tmp_bpmov [tmp2],eax
jmp label_loop
label_exit:
mov eip,oep
mov esp,esp_addr
ret

然后程序脱壳就成功了。

VMP壳

这是现在的主流和脱壳难度最大的壳。

首先一般此类壳都有虚拟机检测,需要过虚拟机检测。

虚拟机检测资料

https://blog.csdn.net/youyou519/article/details/94181836

所以in,str等这些指令加壳程序无法模拟。但是push ebp,mov ebp,esp是可以使用自己编造的指令集替换的。

然后我们看下2.x版本的vmp壳。

od增加插件zeus可以分析得到表单

Load PCode:
01142762   01142762 mov al,byte ptr ds:[esi-1]
           ---------------------------------------------
           Pcode Decode :
0114276C   add al,bl
01142772   neg al
01142778   ror al,1
01142799   add al,0be
011427A5   add bl,al
           ---------------------------------------------
           Dispatch Table :
011427BB   011427BB mov ecx,dword ptr ds:[eax*4+1142a05]
           Dispatch Base : 01142A05
           Dispatch Reg  : ecx
           ---------------------------------------------
           Handler Decode :
0114324A   dec ecx
01143255   add ecx,0
           ---------------------------------------------
           Handler Entry :
01144C82   01144C82 retn 44
           ---------------------------------------------
           VM Initial Info:
           [+00] <- 00000000  RELOC
           [+01] <- 00000000  ANTIDUMP
           [+02] <- 0006FFB0  ecx
           [+03] <- 7FFDE000  ebx
           [+04] <- 7C930208  edi
           [+05] <- 7FFDE000  ebx
           [+06] <- 00000000  eax
           [+07] <- 00000246  EFL
           [+08] <- 7C92E4F4  edx
           [+09] <- FFFFFFFF  esi
           [+0A] <- 0A6462B9  RELOC
           [+0B] <- 8749A2CD  RETADDR
           [+0C] <- C58DE0B9  INITDATA
           ---------------------------------------------
           VMInitKey          : C58DE0B9
           VMDecodeKey        : 010AB3D9
           VMOpcodeStart      : 010AB3D9
010AB3D8   VMEipStart         : 010AB3D8
           VMOpcode Direction  : ↓
           ---------------------------------------------
011421C0   00: 011421C1 ---> 011421C0[VM_Cpuid            ]
011434E2   01: 011434E3 ---> 011434E2[VM_GetR32           ]
0114461F   02: 01144620 ---> 0114461F[VM_WmDs32           ]
01143288   03: 01143289 ---> 01143288[VM_Shl8             ]

比如就是把一条指令cpuid膨胀变成了一个函数。如果像IO指令没法模拟的,就退出虚拟机指令环境,执行原有指令。

然后想过有检测虚拟机的指令,就把他patch掉。这只是思路,具体根据虚拟机不同版本方法有变化。

windows脱壳复习相关推荐

  1. linux 下 upx 脱壳笔记

    linux很少有需要crack的软件,所以最近总是自娱自乐.自己写的软件自己破着玩但是由于都是知道自己的手段,没有什么意思.真的希望有高手们写些crackme for linux . 最近看了看win ...

  2. 索(shen)引(keng)大全

    索(shen)引(keng)大全 (博主已获得称号:挖坑达人lv.5 (QvQ)) 下列各个索(shen)引(keng)不按时间顺序. 学习笔记: 计算机网络_学习笔记 索引 「索引」<Pyth ...

  3. 初入职场必备丨二进制面试问题汇总

    汇编:沫沫 编者按:本贴面试题目汇总来源于线下和网络,仅供求职者面试前参考使用,侵删. 01安全研究岗位 一面 1. 不用+ - * /,输入两位数,打印出结果 示例:输入2   3,输出5 2. 不 ...

  4. 职称计算机隐藏桌面图标,2016职称计算机Windows复习巩固题

    职称计算机Windows考试多做复习巩固题,对考试很有帮助.以下是百分网小编精心为大家整理的2016职称计算机Windows复习巩固题,希望对大家有所帮助!想了解更多相关信息请持续关注我们应届毕业生考 ...

  5. 专转本计算机word知识点,江苏专转本计算机windows和word复习资料(含答案).doc

    Windows 操作系统部分知识点分析 知识点1:windows是一个多任务图形化的操作系统,DOS是一个单任务字符界面的操作系统. [往年考题] 13.下列__D__不属于多用户多任务操作系统的软件 ...

  6. Windows PowerShell 实战指南-附录(复习实验)-实验回顾1

    任务1: 运行一个命令,从而显示应用程序事件日志中最新的100个条目,不要使用Get-WinEvent. 解答: get-eventlog -computername localhost -logna ...

  7. 「信息安全技术」期末复习宝典 【整理完毕】

    文章目录 选择 密码与隐藏技术 数字签名与认证 身份与访问安全 计算机病毒与黑客 网络攻击与防范 网络安全与编程 设备与环境安全 软件保护技术1 软件保护技术2 社会工程学 区块链基础 问答题 1.简 ...

  8. Windows Phone开发(39):漫谈关键帧动画上篇 转:http://blog.csdn.net/tcjiaan/article/details/7550506...

    尽管前面介绍的几种动画会让觉得很好玩了,但是,不知道你是否发现,在前面说到的一系列XXXAnimation中,都有一个共同点,那就是仅仅针对两个值的目标值之间产生动画,如果使用By,将在原值和加上By ...

  9. 计算机应用 含升学方向,对口升学《计算机应用基础》复习资料总汇(含答案))讲述.doc...

    对口升学<计算机应用基础>复习资料总汇 第一部分?? 一.单项选择题 1.世界上第一台电子数字计算机取名为(????). A.UNIVAC????B.EDSAC????C.ENIAC??? ...

  10. Windows Server 2016 笔记

    从业界普遍实践结果来看,Windows Server在服务器领域真是不太好用.但是,有些时候由于种种原因不得不用,所以还是有必要了解一下的.今天参加了一个Windows Server的培训,主要面对W ...

最新文章

  1. Java基础(七)--Exception异常处理
  2. iOS更改AppIcon
  3. 被放弃的概率权,机器下围棋不理会沉没成本
  4. P2339 提交作业usaco
  5. 如何使用Webpack
  6. 140.String Compression
  7. KindEditor在eclipse里的配置方法
  8. html5 加上魔法,简单易懂的React魔法(28):是时候添加一些CSS样式了
  9. C语言九九乘法表的代码(含注释)
  10. 妙算2的串口用自己的接线(杜邦线)连接无人机210或者stm32
  11. 数据科学必备用Python进行描述性统计数据分析详解
  12. Java-Tcp/Ip-CS控制台聊天应用Demo
  13. Ubuntu 20.04/21.04 不能检测到外部HDMI显示器
  14. 人类一败涂地做图教程_人类一败涂地皮肤怎么弄 人类一败涂地皮肤制作教程...
  15. Redis可视化管理工具:Another Redis DeskTop Manager
  16. latex从入门到精通
  17. 文件夹选择框 文件选择框
  18. 【English】新征程,我们在路上
  19. 日语 | 日本50音
  20. 电影-满城尽带黄金甲

热门文章

  1. 计算机网络的产生与发展可分为哪四个阶段,计算机网络形成与发展大致分为如下4个阶段...
  2. 超定方程 matlab,Matlab求解超定方程组实例(精品文档)
  3. 如何使用Python查找文本文件的Zipf分布
  4. 上海域格ASR平台4g模块低功耗应用指导
  5. WEBQQ登陆综合帖
  6. 数据库时间相减_sql中两个时间类型相减得到的值
  7. ubuntu安装maya2011的方法
  8. CG佬的20年:行走于行业的过去与未来
  9. 软件测试常考面试题-软件测试面试宝典(一篇足矣)
  10. 闲聊企业数字化转型(1)-供应链数字化