这是一个SMC补丁的里面的实例,他的方法有一步我完成不了,就自己分析了。大家感兴趣的可以看下。
以下完全自己的看法,如果和大家的看法不同,帮忙指出来一下,谢谢。
SMC补丁:在外壳中就是动态修改代码,由我们把我们的SMC代码写进磁盘文件,然后我们动态引导外壳处理。
先说下第一步:ASProtect外壳有4个解密代码的地址.我们要引导这4个地址,这几个地址都是JMP的形式存在。
jnz Decode
jmp xxxxxx2 修改为我们的地址。因为是动态解码,我们修改下面的地址,就会解码错误
jnz Decode1
jmp xxxxxx3这样依次修改到最后一个解码的地址,就是静态代码了
00468037 50 PUSH EAX
00468038 53 PUSH EBX
00468039 FFB5 ED090000 PUSH DWORD PTR SS:[EBP+9ED]
0046803F 8D45 35 LEA EAX,DWORD PTR SS:[EBP+35]
00468042 50 PUSH EAX
00468043 E9 82000000 JMP InlineMe.004680CA ; 跳到解码地址一
解码地址一,0x0046817B处硬件断点,开始解码地址二
0046816F 81E8 01000000 SUB EAX,1
00468175 0F85 19000000 JNZ InlineMe.00468194 ; 判断解码代码的大小,是否继续解码
0046817B E9 2E000000 JMP InlineMe.004681AE ; 跳到解码地址二
解码地址二,0x468225处硬件断点,跳向解码地址三
00468246 4B DEC EBX
00468247 81FB 34F9FFFF CMP EBX,-6CC ; 以负数形式比较大小
0046824D 0F85 0C000000 JNZ InlineMe.0046825F ; 判断是否继续解码
00468253 8BD1 MOV EDX,ECX
00468255 E9 27000000 JMP InlineMe.00468281 ; 跳向解码地址三
解码地址三,依然断点:
00468354 81EE 01000000 SUB ESI,1 ; 解码大小
0046835A 0F85 0B000000 JNZ InlineMe.0046836B ; 判断解码大小
00468360 E9 23000000 JMP InlineMe.00468388 ; 跳向解码地址4
解码地址4,依然断点
00468419 83EE 01 SUB ESI,1 ; 解码大小
0046841C ^ 0F85 9DFFFFFF JNZ InlineMe.004683BF ; 判断解码大小
00468422 B4 02 MOV AH,2 ; 断点
接下来就是把储存的压缩后的代码解密到分配的内存空间,然后重定向等等,处理,返回到指定虚拟内存空间执行代码:
004684CB 6A 40 PUSH 40
004684CD 68 00100000 PUSH 1000
004684D2 FFB5 08040000 PUSH DWORD PTR SS:[EBP+408] ; 大小
004684D8 6A 00 PUSH 0
004684DA FF95 F0030000 CALL DWORD PTR SS:[EBP+3F0] ; VirtualAlloc分配内存
004684E0 8985 CC010000 MOV DWORD PTR SS:[EBP+1CC],EAX ; EAX=00970000
004684E6 8B9D 00040000 MOV EBX,DWORD PTR SS:[EBP+400]
004684EC 039D 0D040000 ADD EBX,DWORD PTR SS:[EBP+40D]
004684F2 50 PUSH EAX
004684F3 53 PUSH EBX
004684F4 E8 04010000 CALL InlineMe.004685FD ; 解码函数
004684F9 6A 40 PUSH 40
004684FB 68 00100000 PUSH 1000
00468500 FFB5 08040000 PUSH DWORD PTR SS:[EBP+408] ; 大小
00468506 6A 00 PUSH 0
00468508 FF95 F0030000 CALL DWORD PTR SS:[EBP+3F0] ; VirtualAlloc分配内存
0046850E 8985 31040000 MOV DWORD PTR SS:[EBP+431],EAX ; EAX=009C0000
复制过程就是把解码到虚拟内存空间的代码,依次复制到VirtualAlloc第2次的地址,然后定位返回地址。
00468562 8B7C1A 0C MOV EDI,DWORD PTR DS:[EDX+EBX+C]
00468566 0BFF OR EDI,EDI
00468568 74 1E JE SHORT InlineMe.00468588
0046856A 8B4C1A 10 MOV ECX,DWORD PTR DS:[EDX+EBX+10]
0046856E 0BC9 OR ECX,ECX
00468570 74 11 JE SHORT InlineMe.00468583
00468572 03BD D0010000 ADD EDI,DWORD PTR SS:[EBP+1D0]
00468578 8B741A 14 MOV ESI,DWORD PTR DS:[EDX+EBX+14]
0046857C 03F2 ADD ESI,EDX
0046857E C1F9 02 SAR ECX,2
00468581 F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS>
00468583 83C3 28 ADD EBX,28
00468586 ^ EB DA JMP SHORT InlineMe.00468562
接下来这个地址很重要:
004685E0 53 PUSH EBX
004685E1 68 00800000 PUSH 8000
004685E6 6A 00 PUSH 0
004685E8 56 PUSH ESI ; 第一次的VirtualAlloc的地址
004685E9 FF95 F4030000 CALL DWORD PTR SS:[EBP+3F4] ; VirtualFree
004685EF 68 0010A000 PUSH 0A01000 ;返回到这个虚拟空间地址
004685F4 C3 RETN
注意下面
00A010B6 6A 04 PUSH 4
00A010B8 68 00100000 PUSH 1000
00A010BD 68 46050000 PUSH 546 ; 大小
00A010C2 6A 00 PUSH 0
00A010C4 FF95 79294400 CALL DWORD PTR SS:[EBP+442979] ; VirtualAlloc
00A010CA 8985 75294400 MOV DWORD PTR SS:[EBP+442975],EAX ; EAX=00970000
00A010D0 8D9D 452A4400 LEA EBX,DWORD PTR SS:[EBP+442A45]
00A010D6 50 PUSH EAX
00A010D7 53 PUSH EBX
00A010D8 E8 74050000 CALL 00A01651 ; 再次解码,第2次中的压缩代码到第3次的VirtualAlloc
00A010DD 8BC8 MOV ECX,EAX
00A010DF 8DBD 452A4400 LEA EDI,DWORD PTR SS:[EBP+442A45]
00A010E5 8BB5 75294400 MOV ESI,DWORD PTR SS:[EBP+442975]
00A010EB F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] ; 解压出来的代码重新复制到第2次VirtualAlloc的空间
00A010ED 8B85 75294400 MOV EAX,DWORD PTR SS:[EBP+442975]
00A010F3 68 00800000 PUSH 8000
00A010F8 6A 00 PUSH 0
00A010FA 50 PUSH EAX ; 第3次的地址
00A010FB FF95 7D294400 CALL DWORD PTR SS:[EBP+44297D] ; VirtualFree
00A01101 8D85 512C4400 LEA EAX,DWORD PTR SS:[EBP+442C51]
00A01107 50 PUSH EAX ; jmp 0xA0130D
00A01108 C3 RETN
下面这里之后,就是处理E8E9,一系列处理完毕后依然会把解码出来的代码放回VirtualAlloc的第2次:
00A01339 6A 04 PUSH 4
00A0133B 68 00100000 PUSH 1000
00A01340 50 PUSH EAX
00A01341 6A 00 PUSH 0
00A01343 FF95 79294400 CALL DWORD PTR SS:[EBP+442979] ; VirtualAlloc
00A01349 8985 75294400 MOV DWORD PTR SS:[EBP+442975],EAX ; EAX=00970000
00A0134F 56 PUSH ESI
00A01350 8B1E MOV EBX,DWORD PTR DS:[ESI]
00A01352 039D D8304400 ADD EBX,DWORD PTR SS:[EBP+4430D8]
00A01358 50 PUSH EAX
00A01359 53 PUSH EBX
00A0135A E8 F2020000 CALL 00A01651 ; 再次解码
上面是个循环处理,没必要详细了解
看着
00A015C1 61 POPAD
00A015C2 75 08 JNZ SHORT 00A015CC
00A015C4 B8 01000000 MOV EAX,1
00A015C9 C2 0C00 RETN 0C
00A015CC 68 501E9F00 PUSH 9F1E50 ; 新的地址
00A015D1 C3 RETN
009F1E50 55 PUSH EBP
009F1E51 8BEC MOV EBP,ESP
009F1E53 83C4 B4 ADD ESP,-4C
009F1E56 B8 B81B9F00 MOV EAX,9F1BB8
009F1E5B E8 383EFDFF CALL 009C5C98
009F1E60 E8 5B17FDFF CALL 009C35C0 ; 跟进
接下来一直F8,直到下面的地址后才F7跟进,009C3690是一个变形JMP
009C3676 52 PUSH EDX
009C3677 E8 74DAFFFF CALL 009C10F0 ; JMP 到 kernel32.FreeLibrary
009C367C E8 F3FCFFFF CALL 009C3374
009C3681 807B 24 01 CMP BYTE PTR DS:[EBX+24],1
009C3685 75 03 JNZ SHORT 009C368A
009C3687 FF53 28 CALL DWORD PTR DS:[EBX+28]
009C368A 807B 24 00 CMP BYTE PTR DS:[EBX+24],0
009C368E 74 05 JE SHORT 009C3695
009C3690 E8 F7FEFFFF CALL 009C358C ; 跟进
这里:
009F0938 56 PUSH ESI
009F0939 E8 7D000000 CALL 009F09BB ; SEH处理,处理的地址指向下面地址
009F093E 53 PUSH EBX ; SEH处理的地址,断点
上面之后,接下来就是一系列的花指令,jmp等等,注意这条语句
009F0990 1BD1 SBB EDX,ECX
009F0992 5A POP EDX
009F0993 8343 61 0D ADD DWORD PTR DS:[EBX+61],0D ; 记下这里相加后的地址,数据窗口查看,跳过去下个断点
009F0997 81E3 580B2C39 AND EBX,392C0B58
009F099D 5B POP EBX
009F099E 034424 38 ADD EAX,DWORD PTR SS:[ESP+38]
009F09A2 034424 18 ADD EAX,DWORD PTR SS:[ESP+18]
上面过后就是跳到系统代码,恢复SEH,上面下了断点之后运行,就到这里了,这个是重点,依次恢复到下面PUSH的地址,从009F0A0B 68 B0FE9E00 PUSH 9EFEB0开始一次向上恢复SEH,所谓的恢复,就相当于JMP吧:
009F09E1 67:64:8F06 0000 POP DWORD PTR FS:[0]
009F09E7 83C4 04 ADD ESP,4
009F09EA 2BF5 SUB ESI,EBP
009F09EC 5E POP ESI
009F09ED 68 E4DD9C00 PUSH 9CDDE4
009F09F2 68 540A9F00 PUSH 9F0A54
009F09F7 68 94EB9E00 PUSH 9EEB94
009F09FC 68 74F69E00 PUSH 9EF674
009F0A01 68 E0E39E00 PUSH 9EE3E0
009F0A06 68 94D39E00 PUSH 9ED394
009F0A0B 68 B0FE9E00 PUSH 9EFEB0
009F0A10 C3 RETN 完全解码完毕
大家依次F8跟踪,处理SEH的时候就过去断点,每当发现这个特征的时候就去上面的地址下断点。
特征:
009ED7D1 C3 RETN ; 返回到 7C9232A8 (ntdll.7C9232A8)
激动部分一:
009EFEB0 55 PUSH EBP ; 向上拉,就能看见MessageBoxA了,然后一直F8+F7到就是跳到OEP了
009EFEB1 8BEC MOV EBP,ESP
009EFEB3 81C4 F8FEFFFF ADD ESP,-108
009EFEB9 53 PUSH EBX
009EFEBA 56 PUSH ESI
009EFEBB 33C0 XOR EAX,EAX
009EFEBD 8985 F8FEFFFF MOV DWORD PTR SS:[EBP-108],EAX
激动部分二:
009EFDFB 68 30200000 PUSH 2030
009EFE00 A1 38369F00 MOV EAX,DWORD PTR DS:[9F3638]
009EFE05 50 PUSH EAX
009EFE06 A1 34369F00 MOV EAX,DWORD PTR DS:[9F3634]
009EFE0B 50 PUSH EAX
009EFE0C 6A 00 PUSH 0
009EFE0E E8 5561FDFF CALL 009C5F68 ; JMP 到 user32.MessageBoxA
激动部分三:
009EFE79 A1 C4379F00 MOV EAX,DWORD PTR DS:[9F37C4]
009EFE7E C600 E3 MOV BYTE PTR DS:[EAX],0E3
009EFE81 8D55 C8 LEA EDX,DWORD PTR SS:[EBP-38]
009EFE84 A1 2CB69F00 MOV EAX,DWORD PTR DS:[9FB62C]
009EFE89 E8 D692FFFF CALL 009E9164
009EFE8E E8 915DFFFF CALL 009E5C24
009EFE93 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
009EFE96 E8 792DFDFF CALL 009C2C14
009EFE9B E8 60CEFFFF CALL 009ECD00 ; 跳向程序的OEP
JUMP To上面的地址的过程由于粗心大意,又要重新跟踪,我懒得跟踪了。
,感兴趣的自己跟踪吧
。
00453B54 55 PUSH EBP
00453B55 8BEC MOV EBP,ESP
00453B57 83C4 F0 ADD ESP,-10
00453B5A B8 74394500 MOV EAX,InlineMe.00453974
00453B5F E8 FC20FBFF CALL InlineMe.00405C60
00453B64 A1 58504500 MOV EAX,DWORD PTR DS:[455058]
00453B69 8B00 MOV EAX,DWORD PTR DS:[EAX]
00453B6B E8 9CE5FFFF CALL InlineMe.0045210C
00453B70 A1 58504500 MOV EAX,DWORD PTR DS:[455058]
00453B75 8B00 MOV EAX,DWORD PTR DS:[EAX]
00453B77 BA B43B4500 MOV EDX,InlineMe.00453BB4 ; ASCII "Annoying NAG"
00453B7C E8 9BE1FFFF CALL InlineMe.00451D1C
00453B81 8B0D 38514500 MOV ECX,DWORD PTR DS:[455138] ; InlineMe.00456BFC
00453B87 A1 58504500 MOV EAX,DWORD PTR DS:[455058]
00453B8C 8B00 MOV EAX,DWORD PTR DS:[EAX]
00453B8E 8B15 AC364500 MOV EDX,DWORD PTR DS:[4536AC] ; InlineMe.004536F8
00453B94 E8 8BE5FFFF CALL InlineMe.00452124
00453B99 A1 58504500 MOV EAX,DWORD PTR DS:[455058]
00453B9E 8B00 MOV EAX,DWORD PTR DS:[EAX]
00453BA0 E8 FFE5FFFF CALL InlineMe.004521A4
00453BA5 E8 B201FBFF CALL InlineMe.00403D5C
[课程]Linux pwn 探索篇!