简单加密壳代码分析

00438450 >  55              PUSH EBP
00438451    8BEC            MOV EBP,ESP
00438453    83EC 0C         SUB ESP,0xC
//第一个call观察发现没有参数,返回值eax也没被使用,可知这个call没有参数也没有返回值,
//即在C语言 == void fun(void),enter进去观察。(注释1-CALL 004383A0)
00438456    E8 45FFFFFF     CALL 02.004383A0                         ; 初始化函数地址
0043845B    A1 40804300     MOV EAX,DWORD PTR DS:[0x438040]         ; 获取映像基址
00438460    0305 44804300   ADD EAX,DWORD PTR DS:[0x438044]         ; 获取代码RVA
//根据后面的函数猜测到这之前应该是初始化数据。

00438466    8945 F8         MOV DWORD PTR SS:[EBP-0x8],EAX
00438469    C745 FC 0000000>MOV DWORD PTR SS:[EBP-0x4],0x0
00438470    8D4D FC         LEA ECX,DWORD PTR SS:[EBP-0x4]
00438473    51              PUSH ECX
00438474    6A 40           PUSH 0x40
00438476    8B15 4C804300   MOV EDX,DWORD PTR DS:[0x43804C]
//修改的地址是代码段基址
0043847C    52              PUSH EDX
0043847D    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-0x8]
00438480    50              PUSH EAX
//这里看到一个VirtualProtct函数,说明可能要修改页属性,推测这之上几行代码都是它的参数。
00438481    FF15 C0924300   CALL DWORD PTR DS:[0x4392C0]             ; DS:[004392C0]=764750AB (kernel32.VirtualProtect)
00438487    E8 04FEFFFF     CALL 02.00438290
0043848C    8D4D FC         LEA ECX,DWORD PTR SS:[EBP-0x4]
0043848F    51              PUSH ECX
00438490    8B55 FC         MOV EDX,DWORD PTR SS:[EBP-0x4]
00438493    52              PUSH EDX
00438494    A1 4C804300     MOV EAX,DWORD PTR DS:[0x43804C]
00438499    50              PUSH EAX
0043849A    8B4D F8         MOV ECX,DWORD PTR SS:[EBP-0x8]
0043849D    51              PUSH ECX
//果不期然这里还有一个VirtualProtect,这个应该是恢复页属性。
//因为第一个VirtualProtect修改代码段基址,所以监视它,然后步过到这,发现代码被修改了。
//而这两个函数中间只有call 00438290可能修改,enter进去(注释2-call 00438290)
0043849E    FF15 C0924300   CALL DWORD PTR DS:[0x4392C0]             ; DS:[004392C0]=764750AB (kernel32.VirtualProtect)

//这里开始是messagebox
004384A4    6A 04           PUSH 0x4
004384A6    68 2C814300     PUSH 02.0043812C                         ; ASCII "Hello 15PB"
004384AB    68 38814300     PUSH 02.00438138                         ; ASCII "欢迎使用免费加壳程序,是否运行主程序?"
004384B0    6A 00           PUSH 0x0
004384B2    FF15 BC924300   CALL DWORD PTR DS:[0x4392BC]             ; user32.MessageBoxA
004384B8    8945 F4         MOV DWORD PTR SS:[EBP-0xC],EAX
004384BB    837D F4 06      CMP DWORD PTR SS:[EBP-0xC],0x6           ; 判断返回是否yes
004384BF    75 0B           JNZ SHORT 02.004384CC
//这里是messagebox结束

004384C1    E8 1A000000     CALL 02.004384E0

//这里进入就是OEP(注释3-OEP图)了,然而在这里的时候发现IAT被加密了(注释4-IAT加密图)
//然后这中间只有前面这个call 004384E0可能加密。enter进入(注释5-CALL 004384E0)
004384C6  - FF25 3C804300   JMP DWORD PTR DS:[0x43803C]             ; OEP入口
004384CC    6A 00           PUSH 0x0
004384CE    FF15 B8924300   CALL DWORD PTR DS:[0x4392B8]             ; kernel32.ExitProcess
004384D4    8BE5            MOV ESP,EBP
004384D6    5D              POP EBP
004384D7    C3              RETN

注释1-CALL 004383A0

//发现函数中有操作fs寄存器的代码,访问Fs寄存器的一般是访问线程TEB以及PEB结构,再加上获取kernel32基址的话需要访问PEB结构中的模块链表。由以上对PEB和FS寄存器的了解,可知这段代码多半是kernel32基址。往下看会看到熟悉的函数。观察步过前跟步过后的参数推测这个是个初始化函数的地址。
004383A0    55              PUSH EBP
004383A1    8BEC            MOV EBP,ESP
004383A3    51              PUSH ECX
004383A4    56              PUSH ESI
004383A5    C745 FC 0000000>MOV DWORD PTR SS:[EBP-0x4],0x0
004383AC    50              PUSH EAX
004383AD    64:A1 30000000  MOV EAX,DWORD PTR FS:[0x30]             ; 获取PEB
004383B3    8B40 0C         MOV EAX,DWORD PTR DS:[EAX+0xC]
004383B6    8B40 1C         MOV EAX,DWORD PTR DS:[EAX+0x1C]
004383B9    8B00            MOV EAX,DWORD PTR DS:[EAX]
004383BB    8B00            MOV EAX,DWORD PTR DS:[EAX]
004383BD    8B40 08         MOV EAX,DWORD PTR DS:[EAX+0x8]
004383C0    8945 FC         MOV DWORD PTR SS:[EBP-0x4],EAX
004383C3    58              POP EAX
004383C4    8B75 FC         MOV ESI,DWORD PTR SS:[EBP-0x4]
004383C7    E8 F4FEFFFF     CALL 02.004382C0
004383CC    68 C4804300     PUSH 02.004380C4                         ; ASCII "LoadLibraryA"
004383D1    56              PUSH ESI
004383D2    A3 CC924300     MOV DWORD PTR DS:[0x4392CC],EAX
004383D7    FFD0            CALL EAX
004383D9    68 D4804300     PUSH 02.004380D4                         ; ASCII "GetModuleHandleA"
004383DE    56              PUSH ESI
004383DF    A3 C8924300     MOV DWORD PTR DS:[0x4392C8],EAX
004383E4    FF15 CC924300   CALL DWORD PTR DS:[0x4392CC]
004383EA    68 E8804300     PUSH 02.004380E8                         ; ASCII "VirtualProtect"
004383EF    56              PUSH ESI
004383F0    A3 C4924300     MOV DWORD PTR DS:[0x4392C4],EAX
004383F5    FF15 CC924300   CALL DWORD PTR DS:[0x4392CC]
004383FB    68 F8804300     PUSH 02.004380F8                         ; ASCII "user32.dll"
00438400    A3 C0924300     MOV DWORD PTR DS:[0x4392C0],EAX
00438405    FF15 C8924300   CALL DWORD PTR DS:[0x4392C8]
0043840B    68 04814300     PUSH 02.00438104                         ; ASCII "MessageBoxA"
00438410    50              PUSH EAX
00438411    FF15 CC924300   CALL DWORD PTR DS:[0x4392CC]
00438417    68 10814300     PUSH 02.00438110                         ; ASCII "ExitProcess"
0043841C    56              PUSH ESI
0043841D    A3 BC924300     MOV DWORD PTR DS:[0x4392BC],EAX
00438422    FF15 CC924300   CALL DWORD PTR DS:[0x4392CC]
00438428    68 1C814300     PUSH 02.0043811C                         ; ASCII "VirtualAlloc"
0043842D    56              PUSH ESI
0043842E    A3 B8924300     MOV DWORD PTR DS:[0x4392B8],EAX
00438433    FF15 CC924300   CALL DWORD PTR DS:[0x4392CC]
00438439    A3 B4924300     MOV DWORD PTR DS:[0x4392B4],EAX
0043843E    5E              POP ESI
0043843F    8BE5            MOV ESP,EBP
00438441    5D              POP EBP
00438442    C3              RETN

最后

00438439 A3 B4924300 MOV DWORD PTR DS:[0x4392B4],EAX

数据窗口跟随,发现初始化了一些函数

简单加密壳代码分析_第1张图片

注释2-call 00438290

//明显有一行代码是异或,显而易见这个call的功能就是解密代码段
00438290    8B0D 44804300   MOV ECX,DWORD PTR DS:[0x438044]         ; 获取代码段RVA
00438296    33C0            XOR EAX,EAX
00438298    030D 40804300   ADD ECX,DWORD PTR DS:[0x438040]         ; 代码段基址=代码段RVA+映像基址
0043829E    3905 4C804300   CMP DWORD PTR DS:[0x43804C],EAX         ; 代码段长度
004382A4    76 17           JBE SHORT 02.004382BD
004382A6    EB 08           JMP SHORT 02.004382B0
004382A8    8DA424 00000000 LEA ESP,DWORD PTR SS:[ESP]
004382AF    90              NOP
004382B0    803408 15       XOR BYTE PTR DS:[EAX+ECX],0x15           ; 代码段基址+偏移异或代码
004382B4    40              INC EAX
004382B5    3B05 4C804300   CMP EAX,DWORD PTR DS:[0x43804C]
004382BB  ^ 72 F3           JB SHORT 02.004382B0
004382BD    C3              RETN

注释3-OEP图

简单加密壳代码分析_第2张图片

注释4-IAT加密图

简单加密壳代码分析_第3张图片

注释5-CALL 004384E0

//IAT填充,需要先获取函数地址,于是在GetProcAddress下断,找到它,然后跟踪它分析,发现,有一行代码对它的返回值异或,之后将这个值保存在局部变量,紧接申请一个内存,将局部缓冲区的一块原本准备好的内容+刚刚加密的值宝贝走,然后填充到IAT地址。
004385B9    FF15 CC924300   CALL DWORD PTR DS:[0x4392CC]             ; kernel32.GetProcAddress
004385BF    6A 40           PUSH 0x40
004385C1    68 00300000     PUSH 0x3000
004385C6    6A 20           PUSH 0x20
004385C8    35 15151515     XOR EAX,0x15151515                       ; 修改IAT函数
004385CD    6A 00           PUSH 0x0
004385CF    8945 DB         MOV DWORD PTR SS:[EBP-0x25],EAX         ; 保存加密之后的iat函数
004385D2    FF15 B4924300   CALL DWORD PTR DS:[0x4392B4]             ; kernel32.VirtualAlloc
004385D8    F30F6F45 D0     MOVDQU XMM0,DQWORD PTR SS:[EBP-0x30]     ; 移位64位到数据到mm0
004385DD    8B55 CC         MOV EDX,DWORD PTR SS:[EBP-0x34]
004385E0    F30F7F00        MOVDQU DQWORD PTR DS:[EAX],XMM0         ; 赋值给申请的空间
004385E4    F30F6F45 E0     MOVDQU XMM0,DQWORD PTR SS:[EBP-0x20]
004385E9    F30F7F40 10     MOVDQU DQWORD PTR DS:[EAX+0x10],XMM0
004385EE    8907            MOV DWORD PTR DS:[EDI],EAX               ; 将函数压入堆栈
004385F0    8B4E 04         MOV ECX,DWORD PTR DS:[ESI+0x4]
004385F3    83C6 04         ADD ESI,0x4
004385F6    8BFE            MOV EDI,ESI
004385F8    85C9            TEST ECX,ECX

简单加密壳代码分析_第4张图片

转载于:https://www.cnblogs.com/ltyandy/p/11289565.html

你可能感兴趣的:(数据结构与算法,c/c++)