- UID
- 74208
注册时间2014-3-1
阅读权限30
最后登录1970-1-1
龙战于野
TA的每日心情 | 无聊 2016-10-10 10:27 |
---|
签到天数: 26 天 [LV.4]偶尔看看III
|
本帖最后由 Crack_Qs 于 2015-6-14 17:57 编辑
只是感兴趣,大牛路过.
默笙妹子发来一个被用SMC方式破解的一个软件,于是研究其SMC中的ShellCode.
//////////////////////////////////////////////////////////////////////////////////////////////////
执行流程:
1.首先得到kernel32的ImageBase为起始解析PE,得到导出表.
2.然后取出GetProcAddress函数地址,获取指定的API
3.Api hook破解该软件
分析代码:
- 00400380 60 pushad ; 保存寄存器环境
- 00400381 8B4424 44 mov eax, dword ptr [esp+0x44]
- 00400385 25 0000FFFF and eax, 0xFFFF0000 ; 不为序号导出
- 0040038A 66:8138 4D5A cmp word ptr [eax], 0x5A4D ; 判断MZ
- 0040038F 74 07 je short 00400398 ; 该判断成立即意味着已经得到kernel32的imageBase
- 00400391 2D 00100000 sub eax, 0x1000 ; 内存中4K对齐,挪动到kernel32 dll的头部
- 00400396 ^ EB F2 jmp short 0040038A ; 循环得到kernel32 imagebase
- 获得一个存放kernel32_ImageBase的指针:
- 00400398 50 push eax ; eax == kernel32_ImageBase
- 00400399 E8 C2000000 call 00400460 ; push 0x0040039E
- 0040039E 59 pop ecx
- 0040039F 58 pop eax
- 00400460:
- 00400460 E8 F5FFFFFF call 0040045A
- 00400465 0000 add byte ptr [eax], al
- 0040045A:
- 0040045A 58 pop eax
- 0040045B 870424 xchg dword ptr [esp], eax
- 0040045E 50 push eax
- 0040045F C3 retn
- 进函数时栈布局
- $ ==> > 00400465 __CALL_RET_EIP -> EAX
- $+4 > 0040039E _CALL_RET_EIP ->
- $+8 > 7C800000 kernel32_ImageBase
- 出函数时栈布局
- $ ==> > 0040039E _CALL_RET_EIP
- $+4 > 00400465 __CALL_RET_EIP
- $+8 > 7C800000 kernel32.7C800000
- 得出的结论即是,mov ecx,00400465(kernel32_ImageBase),其他忽略不谈
- 通过PE结构的固定偏移算出kernel32.dll的导出表,为后面顺利取出WINAPI做准备
- 004003A0 8BD8 mov ebx, eax ; ebx == kernel32_ImageBase(SAVE)
- 004003A2 8B48 3C mov ecx, dword ptr [eax+0x3C] ; ecx == e_lfanew(offset)
- 004003A5 03C8 add ecx, eax ; ecx == kernel32_Image_NT_Header
- 004003A7 8B51 78 mov edx, dword ptr [ecx+0x78] ; edx == Kernel32_Export_Table(offset)
- 004003AA 03D0 add edx, eax ; EDX == Kernel32_ExportTable_VA
- 同上冲定位函数,直接给出结果 mov ecx,00400465
- 004003AC 50 push eax
- 004003AD E8 AE000000 call 00400460
- 004003B2 59 pop ecx
- 004003B3 58 pop eax
- 004003B4 83C1 08 add ecx, 0x8 ; ecx == pNewEipAddr
- 004003B7 50 push eax ; kernel32_ImageBase
- 004003B8 51 push ecx ; ecx == pNewEipAddr
- 004003B9 E8 9C000000 call 0040045A
- 0040045A:
- 0040045A 58 pop eax
- 0040045B 870424 xchg dword ptr [esp], eax
- 0040045E 50 push eax
- 0040045F C3 retn
- 有意思的在于下面的一句,之前没注意看,此时才发现&pKernel32 + 8的位置是接下来运算的中的shellcode的一部分
- 004003B4 83C1 08 add ecx, 0x8 ; ecx == 0040046D(pKernel32)
- 004003B7 50 push eax ; kernel32_ImageBase
- 004003B8 51 push ecx ; ecx == pUnKnowAddr
- 004003B9 E8 9C000000 call 0040045A
- 0040046D 59 pop ecx
- 0040046E 58 pop eax ; eax == Kernel32_ImageBase
- 0040046F 8B4A 20 mov ecx, dword ptr [edx+0x20] ; ecx == Kernel32_ExprotTable_AddrOfNames(offset)
- 00400472 52 push edx ; edx == Kernel32_ExportTable_VA
- 00400473 03C1 add eax, ecx ; eax == Kernel32_ExprotTable_AddrOfNames
- 00400475 53 push ebx ; ebx == Kernel32_ImageBase(SAVE)
- 00400476 33DB xor ebx, ebx
- 00400478 EB 04 jmp short 0040047E
- 0040047A 83C0 04 add eax, 0x4
- 0040047D 43 inc ebx
- 0040047E 8B0C24 mov ecx, dword ptr [esp] ; ecx == Kernel32_ImageBase
- 00400481 8B10 mov edx, dword ptr [eax] ; api offset
- 00400483 03D1 add edx, ecx ; edx == API Addr
- 00400485 8BFA mov edi, edx ; Sava Api Addr
- 00400487 33C9 xor ecx, ecx
- 00400489 50 push eax ; Kernel32_ExprotTable_AddrOfNames(Save)
- 0040048A 33C0 xor eax, eax
- 0040048C 41 inc ecx ; 计数器(API Name Len)
- 0040048D AE scas byte ptr es:[edi]
- 0040048E ^ 75 FC jnz short 0040048C
- 00400490 49 dec ecx
- 00400491 E8 28FFFFFF call 004003BE
- 004003BE E8 97000000 call 0040045A
- 004003C3 47 inc edi ;看不懂正常,因为是字符串
- 004003C4 65:74 50 je short 00400417
- 004003C7 72 6F jb short 00400438
- 004003C9 6341 64 arpl word ptr [ecx+0x64], ax
- 004003CC 64:72 65 jb short 00400434
- 004003CF 73 73 jnb short 00400444
- 004003D1 0000 add byte ptr [eax], al
- 004003D3 56 push esi
- 004003D4 6972 74 75616C5>imul esi, dword ptr [edx+0x74], 0x506>
- 004003DB 72 6F jb short 0040044C
- 004003DD 74 65 je short 00400444
- 004003DF 637400 00 arpl word ptr [eax+eax], si
- 004003E3 4D dec ebp
- 004003E4 61 popad
- 004003E5 70 56 jo short 0040043D
- 004003E7 6965 77 4F66466>imul esp, dword ptr [ebp+0x77], 0x694>
- 004003EE 6C ins byte ptr es:[edi], dx
- 004003EF 65:0000 add byte ptr gs:[eax], al
- 004003F2 0043 72 add byte ptr [ebx+0x72], al
- 004003F5 65:61 popad
- 004003F7 74 65 je short 0040045E
- 004003F9 46 inc esi
- 004003FA 696C65 41 00000>imul ebp, dword ptr [ebp+0x41], 0x0
- 00400402 0056 69 add byte ptr [esi+0x69], dl
- 00400405 72 74 jb short 0040047B
- 00400407 75 61 jnz short 0040046A
- 00400409 6C ins byte ptr es:[edi], dx
- 0040040A 41 inc ecx
- 0040040B 6C ins byte ptr es:[edi], dx
- 0040040C 6C ins byte ptr es:[edi], dx
- 0040040D 6F outs dx, dword ptr es:[edi]
- 0040040E 6300 arpl word ptr [eax], ax
- 004003C3 47 65 74 50 72 6F 63 41 64 64 72 65 73 73 00 00 GetProcAddress..
- 004003D3 56 69 72 74 75 61 6C 50 72 6F 74 65 63 74 00 00 VirtualProtect..
- 004003E3 4D 61 70 56 69 65 77 4F 66 46 69 6C 65 00 00 00 MapViewOfFile...
- 004003F3 43 72 65 61 74 65 46 69 6C 65 41 00 00 00 00 00 CreateFileA.....
- 00400403 56 69 72 74 75 61 6C 41 6C 6C 6F 63 00 00 00 00 VirtualAlloc....
- 当前在获取GetProcAddress
- 0040047A 83C0 04 add eax, 0x4 ; 挪动指针,方便取新API
- 0040047D 43 inc ebx ; 计数器
- 0040047E 8B0C24 mov ecx, dword ptr [esp] ; ecx == Kernel32_ImageBase
- 00400481 8B10 mov edx, dword ptr [eax] ; api offset
- 00400483 03D1 add edx, ecx ; edx == API Addr
- 00400485 8BFA mov edi, edx ; Sava Api Addr
- 00400487 33C9 xor ecx, ecx
- 00400489 50 push eax ; Kernel32_ExprotTable_AddrOfNames(Save)
- 0040048A 33C0 xor eax, eax
- 0040048C 41 inc ecx ; 计数器(API Name Len)
- 0040048D AE scas byte ptr es:[edi]
- 0040048E ^ 75 FC jnz short 0040048C
- 00400490 49 dec ecx
- 00400491 E8 28FFFFFF call 004003BE
- 00400496 5E pop esi ; esi == "GetProcAddress"
- 00400497 58 pop eax ; eax == Kernel32_ExprotTable_AddrOfNames
- 00400498 8BFA mov edi, edx ; 当前遍历出的API
- 0040049A F3:A6 repe cmps byte ptr es:[edi], byte ptr>; 比较是否一致
- 0040049C ^ 75 DC jnz short 0040047A ; 不一致开始下一轮
- 0040049E 58 pop eax ; eax == Kernel32_ImageBase
- 0040049F 870424 xchg dword ptr [esp], eax ; 与Kernel32_Export_Table_VA交换
- 004004A2 90 nop
- 004004A3 83C0 1C add eax, 0x1C ; eax == Kernel32_ExportTable_AddrOfFunc(offset)
- 004004A6 8B00 mov eax, dword ptr [eax] ; eax == Kernel32_ExportTable_AddrOfFunc
- 004004A8 50 push eax
- 004004A9 8B4C24 04 mov ecx, dword ptr [esp+0x4] ; ecx == Kernel32_ImageBase
- 004004AD 8BFF mov edi, edi
- 004004AF 58 pop eax
- 004004B0 03C1 add eax, ecx ; eax == Kernel32_ExportTable_AddrOfFunc(VA)
- 004004B2 8B0498 mov eax, dword ptr [eax+ebx*4] ; 利用计数器查表得到API offset
- 004004B5 03C1 add eax, ecx ; 得到API
- 004004B7 50 push eax ; push api addr
- 004004B8 E8 A3FFFFFF call 00400460 ; 执行
- 004004C8 59 pop ecx
- 004004C9 58 pop eax
- 004004CA 83C1 10 add ecx, 0x10 ; 取自定义API名字表中的下一项(VirtualProtect)
- 004004CD 51 push ecx
- 004004CE 8BD0 mov edx, eax
- 004004D0 E8 8BFFFFFF call 00400460
- 004004D5 59 pop ecx
- 004004D6 58 pop eax
- 004004D7 50 push eax ; push lpProcName
- 004004D8 FF31 push dword ptr [ecx] ; hModule
- 004004DA FFD2 call edx ; edx == GetProcAddress
- 004004DC 50 push eax ; api(VirtualProtect) addr
- 004004DD E8 4EFEFFFF call 00400330
- 00400330 8BF8 mov edi, eax
- 00400332 50 push eax
- 00400333 54 push esp
- 00400334 6A 40 push 0x40 ; VirtualProtect 参数 PAGE_EXECUTE_READWRITE
- 00400336 68 00010000 push 0x100 ; VirtualProtect 参数 Size
- 0040033B E8 F3000000 call 00400433
- 00400436 0000 add byte ptr [eax], al
- 00400438 D4 1A aam 0x1A ; VirtualProtectEx addr
- 0040043A 807C95 B9 80 cmp byte ptr [ebp+edx*4-0x47], 0x80 ; MapViewOfFile addr
- 0040043F 7C 00 jl short 00400441
- 00400350 8B4424 08 mov eax, dword ptr [esp+0x8]
- 00400354 8901 mov dword ptr [ecx], eax ; 保存 kernel32_imagebase
- 00400356 8959 04 mov dword ptr [ecx+0x4], ebx ; 保存GetProcAddress
- 00400359 E8 D5000000 call 00400433
- 0040035E 59 pop ecx
- 0040035F C3 retn
- 00400580 59 pop ecx
- 00400581 58 pop eax
- 00400582 50 push eax ; push lpProcName(MapViewOffile)
- 00400583 FF31 push dword ptr [ecx] ; hModule
- 00400585 FF51 04 call dword ptr [ecx+0x4] ; kernel32.GetProcAddress
- 保存了前五字节,应是要进入HOOK:
- 004005B8 59 pop ecx
- 004005B9 58 pop eax
- 004005BA 83C1 14 add ecx, 0x14
- 004005BD 8B10 mov edx, dword ptr [eax]
- 004005BF 66:8B58 04 mov bx, word ptr [eax+0x4]
- 004005C3 8911 mov dword ptr [ecx], edx
- 004005C5 66:8959 04 mov word ptr [ecx+0x4], bx
- 004005C9 C3 retn
- HOOK操作:
- 00400606 59 pop ecx
- 00400607 58 pop eax
- 00400608 C600 68 mov byte ptr [eax], 0x68
- 0040060B 8948 01 mov dword ptr [eax+0x1], ecx
- 0040060E C640 05 C3 mov byte ptr [eax+0x5], 0xC3
- 00400612 C3 retn
- 恢复环境:
- 00400598 61 popad
- 00400599 830424 07 add dword ptr [esp], 0x7
- 0040059D C3 retn
- CreateFile挂后:
- 7C801A28 > 68 8F074000 push 0x40078F ; ASCII "PQ?"
- 7C801A2D C3 retn
- MapViewOffile挂后:
- 7C80B995 > 68 38064000 push 0x400638
- 7C80B99A C3 retn
- 如何构造的shellcode已经分析完成,下面看是如何破解的:
- hook:
- 004007CC 50 push eax
- 004007CD 83C0 75 add eax, 0x75
- 004007D0 B9 16924300 mov ecx, 00439216
- 004007D5 2BC1 sub eax, ecx
- 004007D7 C601 E8 mov byte ptr [ecx], 0xE8
- 004007DA 8941 01 mov dword ptr [ecx+0x1], eax
- 004007DD C741 05 8BCEEBA>mov dword ptr [ecx+0x5], 0xACEBCE8B
- 004007E4 83E9 4D sub ecx, 0x4D
- 004007E7 66:C701 EB4B mov word ptr [ecx], 0x4BEB
- 004007EC 830424 01 add dword ptr [esp], 0x1
- 004007F0 81C1 95220000 add ecx, 0x2295
- 004007F6 C701 33C04083 mov dword ptr [ecx], 0x8340C033
- 004007FC 81C1 D2830000 add ecx, 0x83D2
- 00400802 66:C701 C390 mov word ptr [ecx], 0x90C3
- 00400807 C3 retn
复制代码
Patch Code(只是简单跟了下,估计不全只简单跟了下hook createfile的部分,没测试过):
- 1.
- 004391c9:
- jmp PatchAddr
- PatchAddr:
- call PatchFun(00400810)
- 恢复原流程:
- mov ecx, esi
- jmp 004391CB
- 2.
- 0043B45E |. 8B07 mov eax, dword ptr [edi]
- 0043B460 |. 48 dec eax ; Switch (cases 1..C)
- 0043B461 |. 83F8 0B cmp eax, 0xB
- 0043B464 |. 0F87 95020000 ja 0043B6FF
- 0043B45E |. 33C0 xor eax, eax
- 0043B460 |. 40 inc eax ; Switch (cases 1..C)
- 0043B461 |. 83F8 0B cmp eax, 0xB
- 0043B464 |. 0F87 95020000 ja 0043B6FF
- 3.
- 00443830 . 6A FF push -0x1
- 00443830 . C3 retn
- 00443831 ? 90 nop
复制代码
ShellcodeBin.rar
(1.14 MB, 下载次数: 3)
|
评分
-
查看全部评分
|