飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 4310|回复: 8

[原创] 一段被破解程序中的shellcode分析

[复制链接]
  • TA的每日心情
    无聊
    2016-10-10 10:27
  • 签到天数: 26 天

    [LV.4]偶尔看看III

    发表于 2015-6-14 17:42:55 | 显示全部楼层 |阅读模式
    本帖最后由 Crack_Qs 于 2015-6-14 17:57 编辑

    只是感兴趣,大牛路过.
    默笙妹子发来一个被用SMC方式破解的一个软件,于是研究其SMC中的ShellCode.
    //////////////////////////////////////////////////////////////////////////////////////////////////
    执行流程:
    1.首先得到kernel32的ImageBase为起始解析PE,得到导出表.
    2.然后取出GetProcAddress函数地址,获取指定的API
    3.Api hook破解该软件

    分析代码:
    1. 00400380     60              pushad                                   ; 保存寄存器环境
    2. 00400381     8B4424 44       mov     eax, dword ptr [esp+0x44]
    3. 00400385     25 0000FFFF     and     eax, 0xFFFF0000                  ; 不为序号导出
    4. 0040038A     66:8138 4D5A    cmp     word ptr [eax], 0x5A4D           ; 判断MZ
    5. 0040038F     74 07           je      short 00400398                   ; 该判断成立即意味着已经得到kernel32的imageBase
    6. 00400391     2D 00100000     sub     eax, 0x1000                      ; 内存中4K对齐,挪动到kernel32 dll的头部
    7. 00400396   ^ EB F2           jmp     short 0040038A                   ; 循环得到kernel32 imagebase

    8. 获得一个存放kernel32_ImageBase的指针:
    9. 00400398     50              push    eax                              ; eax == kernel32_ImageBase
    10. 00400399     E8 C2000000     call    00400460                         ; push 0x0040039E
    11. 0040039E     59              pop     ecx
    12. 0040039F     58              pop     eax
    13. 00400460:
    14.     00400460     E8 F5FFFFFF     call    0040045A
    15.     00400465     0000            add     byte ptr [eax], al
    16. 0040045A:
    17.     0040045A     58              pop     eax
    18.     0040045B     870424          xchg    dword ptr [esp], eax
    19.     0040045E     50              push    eax
    20.     0040045F     C3              retn

    21. 进函数时栈布局
    22. $ ==>    > 00400465  __CALL_RET_EIP -> EAX
    23. $+4      > 0040039E  _CALL_RET_EIP  ->
    24. $+8      > 7C800000  kernel32_ImageBase

    25. 出函数时栈布局
    26. $ ==>    > 0040039E  _CALL_RET_EIP
    27. $+4      > 00400465  __CALL_RET_EIP
    28. $+8      > 7C800000  kernel32.7C800000
    29. 得出的结论即是,mov ecx,00400465(kernel32_ImageBase),其他忽略不谈

    30. 通过PE结构的固定偏移算出kernel32.dll的导出表,为后面顺利取出WINAPI做准备
    31. 004003A0     8BD8            mov     ebx, eax                         ; ebx == kernel32_ImageBase(SAVE)
    32. 004003A2     8B48 3C         mov     ecx, dword ptr [eax+0x3C]        ; ecx == e_lfanew(offset)
    33. 004003A5     03C8            add     ecx, eax                         ; ecx == kernel32_Image_NT_Header
    34. 004003A7     8B51 78         mov     edx, dword ptr [ecx+0x78]        ; edx == Kernel32_Export_Table(offset)
    35. 004003AA     03D0            add     edx, eax                         ; EDX == Kernel32_ExportTable_VA

    36. 同上冲定位函数,直接给出结果 mov ecx,00400465
    37. 004003AC     50              push    eax
    38. 004003AD     E8 AE000000     call    00400460
    39. 004003B2     59              pop     ecx
    40. 004003B3     58              pop     eax
    41. 004003B4     83C1 08         add     ecx, 0x8                         ; ecx == pNewEipAddr
    42. 004003B7     50              push    eax                              ; kernel32_ImageBase
    43. 004003B8     51              push    ecx                              ; ecx == pNewEipAddr
    44. 004003B9     E8 9C000000     call    0040045A
    45. 0040045A:
    46.     0040045A     58              pop     eax
    47.     0040045B     870424          xchg    dword ptr [esp], eax
    48.     0040045E     50              push    eax
    49.     0040045F     C3              retn

    50. 有意思的在于下面的一句,之前没注意看,此时才发现&pKernel32 + 8的位置是接下来运算的中的shellcode的一部分
    51. 004003B4    83C1 08         add     ecx, 0x8                         ; ecx == 0040046D(pKernel32)
    52. 004003B7    50              push    eax                              ; kernel32_ImageBase
    53. 004003B8    51              push    ecx                              ; ecx == pUnKnowAddr
    54. 004003B9    E8 9C000000     call    0040045A

    55. 0040046D    59              pop     ecx
    56. 0040046E    58              pop     eax                              ; eax == Kernel32_ImageBase
    57. 0040046F    8B4A 20         mov     ecx, dword ptr [edx+0x20]        ; ecx == Kernel32_ExprotTable_AddrOfNames(offset)
    58. 00400472    52              push    edx                              ; edx == Kernel32_ExportTable_VA
    59. 00400473    03C1            add     eax, ecx                         ; eax == Kernel32_ExprotTable_AddrOfNames
    60. 00400475    53              push    ebx                              ; ebx == Kernel32_ImageBase(SAVE)
    61. 00400476    33DB            xor     ebx, ebx
    62. 00400478    EB 04           jmp     short 0040047E
    63. 0040047A    83C0 04         add     eax, 0x4
    64. 0040047D    43              inc     ebx
    65. 0040047E    8B0C24          mov     ecx, dword ptr [esp]             ; ecx == Kernel32_ImageBase
    66. 00400481    8B10            mov     edx, dword ptr [eax]             ; api offset
    67. 00400483    03D1            add     edx, ecx                         ; edx == API Addr
    68. 00400485    8BFA            mov     edi, edx                         ; Sava Api Addr
    69. 00400487    33C9            xor     ecx, ecx
    70. 00400489    50              push    eax                              ; Kernel32_ExprotTable_AddrOfNames(Save)
    71. 0040048A    33C0            xor     eax, eax
    72. 0040048C    41              inc     ecx                              ; 计数器(API Name Len)
    73. 0040048D    AE              scas    byte ptr es:[edi]
    74. 0040048E  ^ 75 FC           jnz     short 0040048C
    75. 00400490    49              dec     ecx
    76. 00400491    E8 28FFFFFF     call    004003BE

    77. 004003BE    E8 97000000     call    0040045A
    78. 004003C3    47              inc     edi                              ;看不懂正常,因为是字符串
    79. 004003C4    65:74 50        je      short 00400417
    80. 004003C7    72 6F           jb      short 00400438
    81. 004003C9    6341 64         arpl    word ptr [ecx+0x64], ax
    82. 004003CC    64:72 65        jb      short 00400434
    83. 004003CF    73 73           jnb     short 00400444
    84. 004003D1    0000            add     byte ptr [eax], al
    85. 004003D3    56              push    esi
    86. 004003D4    6972 74 75616C5>imul    esi, dword ptr [edx+0x74], 0x506>
    87. 004003DB    72 6F           jb      short 0040044C
    88. 004003DD    74 65           je      short 00400444
    89. 004003DF    637400 00       arpl    word ptr [eax+eax], si
    90. 004003E3    4D              dec     ebp
    91. 004003E4    61              popad
    92. 004003E5    70 56           jo      short 0040043D
    93. 004003E7    6965 77 4F66466>imul    esp, dword ptr [ebp+0x77], 0x694>
    94. 004003EE    6C              ins     byte ptr es:[edi], dx
    95. 004003EF    65:0000         add     byte ptr gs:[eax], al
    96. 004003F2    0043 72         add     byte ptr [ebx+0x72], al
    97. 004003F5    65:61           popad
    98. 004003F7    74 65           je      short 0040045E
    99. 004003F9    46              inc     esi
    100. 004003FA    696C65 41 00000>imul    ebp, dword ptr [ebp+0x41], 0x0
    101. 00400402    0056 69         add     byte ptr [esi+0x69], dl
    102. 00400405    72 74           jb      short 0040047B
    103. 00400407    75 61           jnz     short 0040046A
    104. 00400409    6C              ins     byte ptr es:[edi], dx
    105. 0040040A    41              inc     ecx
    106. 0040040B    6C              ins     byte ptr es:[edi], dx
    107. 0040040C    6C              ins     byte ptr es:[edi], dx
    108. 0040040D    6F              outs    dx, dword ptr es:[edi]
    109. 0040040E    6300            arpl    word ptr [eax], ax

    110. 004003C3  47 65 74 50 72 6F 63 41 64 64 72 65 73 73 00 00  GetProcAddress..
    111. 004003D3  56 69 72 74 75 61 6C 50 72 6F 74 65 63 74 00 00  VirtualProtect..
    112. 004003E3  4D 61 70 56 69 65 77 4F 66 46 69 6C 65 00 00 00  MapViewOfFile...
    113. 004003F3  43 72 65 61 74 65 46 69 6C 65 41 00 00 00 00 00  CreateFileA.....
    114. 00400403  56 69 72 74 75 61 6C 41 6C 6C 6F 63 00 00 00 00  VirtualAlloc....

    115. 当前在获取GetProcAddress
    116. 0040047A    83C0 04         add     eax, 0x4                         ; 挪动指针,方便取新API
    117. 0040047D    43              inc     ebx                              ; 计数器
    118. 0040047E    8B0C24          mov     ecx, dword ptr [esp]             ; ecx == Kernel32_ImageBase
    119. 00400481    8B10            mov     edx, dword ptr [eax]             ; api offset
    120. 00400483    03D1            add     edx, ecx                         ; edx == API Addr
    121. 00400485    8BFA            mov     edi, edx                         ; Sava Api Addr
    122. 00400487    33C9            xor     ecx, ecx
    123. 00400489    50              push    eax                              ; Kernel32_ExprotTable_AddrOfNames(Save)
    124. 0040048A    33C0            xor     eax, eax
    125. 0040048C    41              inc     ecx                              ; 计数器(API Name Len)
    126. 0040048D    AE              scas    byte ptr es:[edi]
    127. 0040048E  ^ 75 FC           jnz     short 0040048C
    128. 00400490    49              dec     ecx
    129. 00400491    E8 28FFFFFF     call    004003BE
    130. 00400496    5E              pop     esi                              ; esi == "GetProcAddress"
    131. 00400497    58              pop     eax                              ; eax == Kernel32_ExprotTable_AddrOfNames
    132. 00400498    8BFA            mov     edi, edx                         ; 当前遍历出的API
    133. 0040049A    F3:A6           repe    cmps byte ptr es:[edi], byte ptr>; 比较是否一致
    134. 0040049C  ^ 75 DC           jnz     short 0040047A                   ; 不一致开始下一轮
    135. 0040049E    58              pop     eax                              ; eax == Kernel32_ImageBase
    136. 0040049F    870424          xchg    dword ptr [esp], eax             ; 与Kernel32_Export_Table_VA交换
    137. 004004A2    90              nop
    138. 004004A3    83C0 1C         add     eax, 0x1C                        ; eax == Kernel32_ExportTable_AddrOfFunc(offset)
    139. 004004A6    8B00            mov     eax, dword ptr [eax]             ; eax == Kernel32_ExportTable_AddrOfFunc
    140. 004004A8    50              push    eax
    141. 004004A9    8B4C24 04       mov     ecx, dword ptr [esp+0x4]         ; ecx == Kernel32_ImageBase
    142. 004004AD    8BFF            mov     edi, edi
    143. 004004AF    58              pop     eax
    144. 004004B0    03C1            add     eax, ecx                         ; eax == Kernel32_ExportTable_AddrOfFunc(VA)
    145. 004004B2    8B0498          mov     eax, dword ptr [eax+ebx*4]       ; 利用计数器查表得到API offset
    146. 004004B5    03C1            add     eax, ecx                         ; 得到API
    147. 004004B7    50              push    eax                              ; push api addr
    148. 004004B8    E8 A3FFFFFF     call    00400460                         ; 执行

    149. 004004C8    59              pop     ecx
    150. 004004C9    58              pop     eax
    151. 004004CA    83C1 10         add     ecx, 0x10                        ; 取自定义API名字表中的下一项(VirtualProtect)
    152. 004004CD    51              push    ecx
    153. 004004CE    8BD0            mov     edx, eax
    154. 004004D0    E8 8BFFFFFF     call    00400460

    155. 004004D5    59              pop     ecx
    156. 004004D6    58              pop     eax
    157. 004004D7    50              push    eax                              ; push lpProcName
    158. 004004D8    FF31            push    dword ptr [ecx]                  ; hModule
    159. 004004DA    FFD2            call    edx                              ; edx == GetProcAddress
    160. 004004DC    50              push    eax                              ; api(VirtualProtect) addr
    161. 004004DD    E8 4EFEFFFF     call    00400330

    162. 00400330     8BF8            mov     edi, eax
    163. 00400332     50              push    eax
    164. 00400333     54              push    esp
    165. 00400334     6A 40           push    0x40                            ; VirtualProtect 参数 PAGE_EXECUTE_READWRITE
    166. 00400336     68 00010000     push    0x100                           ; VirtualProtect 参数 Size
    167. 0040033B     E8 F3000000     call    00400433

    168. 00400436      0000            add     byte ptr [eax], al
    169. 00400438      D4 1A           aam     0x1A                             ; VirtualProtectEx addr
    170. 0040043A      807C95 B9 80    cmp     byte ptr [ebp+edx*4-0x47], 0x80  ; MapViewOfFile addr
    171. 0040043F      7C 00           jl      short 00400441

    172. 00400350      8B4424 08       mov     eax, dword ptr [esp+0x8]
    173. 00400354      8901            mov     dword ptr [ecx], eax             ; 保存 kernel32_imagebase
    174. 00400356      8959 04         mov     dword ptr [ecx+0x4], ebx         ; 保存GetProcAddress
    175. 00400359      E8 D5000000     call    00400433
    176. 0040035E      59              pop     ecx
    177. 0040035F      C3              retn

    178. 00400580     59              pop     ecx
    179. 00400581     58              pop     eax
    180. 00400582     50              push    eax                              ; push lpProcName(MapViewOffile)
    181. 00400583     FF31            push    dword ptr [ecx]                  ; hModule
    182. 00400585     FF51 04         call    dword ptr [ecx+0x4]              ; kernel32.GetProcAddress

    183. 保存了前五字节,应是要进入HOOK:
    184. 004005B8     59              pop     ecx
    185. 004005B9     58              pop     eax
    186. 004005BA     83C1 14         add     ecx, 0x14
    187. 004005BD     8B10            mov     edx, dword ptr [eax]
    188. 004005BF     66:8B58 04      mov     bx, word ptr [eax+0x4]
    189. 004005C3     8911            mov     dword ptr [ecx], edx
    190. 004005C5     66:8959 04      mov     word ptr [ecx+0x4], bx
    191. 004005C9     C3              retn

    192. HOOK操作:
    193. 00400606     59              pop     ecx
    194. 00400607     58              pop     eax
    195. 00400608     C600 68         mov     byte ptr [eax], 0x68
    196. 0040060B     8948 01         mov     dword ptr [eax+0x1], ecx
    197. 0040060E     C640 05 C3      mov     byte ptr [eax+0x5], 0xC3
    198. 00400612     C3              retn

    199. 恢复环境:
    200. 00400598     61              popad
    201. 00400599     830424 07       add     dword ptr [esp], 0x7
    202. 0040059D     C3              retn

    203. CreateFile挂后:
    204. 7C801A28 >  68 8F074000     push    0x40078F                         ; ASCII "PQ?"
    205. 7C801A2D    C3              retn

    206. MapViewOffile挂后:
    207. 7C80B995 >  68 38064000     push    0x400638
    208. 7C80B99A    C3              retn


    209. 如何构造的shellcode已经分析完成,下面看是如何破解的:
    210. hook:
    211. 004007CC    50              push    eax
    212. 004007CD    83C0 75         add     eax, 0x75
    213. 004007D0    B9 16924300     mov     ecx, 00439216
    214. 004007D5    2BC1            sub     eax, ecx
    215. 004007D7    C601 E8         mov     byte ptr [ecx], 0xE8
    216. 004007DA    8941 01         mov     dword ptr [ecx+0x1], eax
    217. 004007DD    C741 05 8BCEEBA>mov     dword ptr [ecx+0x5], 0xACEBCE8B
    218. 004007E4    83E9 4D         sub     ecx, 0x4D
    219. 004007E7    66:C701 EB4B    mov     word ptr [ecx], 0x4BEB
    220. 004007EC    830424 01       add     dword ptr [esp], 0x1
    221. 004007F0    81C1 95220000   add     ecx, 0x2295
    222. 004007F6    C701 33C04083   mov     dword ptr [ecx], 0x8340C033
    223. 004007FC    81C1 D2830000   add     ecx, 0x83D2
    224. 00400802    66:C701 C390    mov     word ptr [ecx], 0x90C3
    225. 00400807    C3              retn
    复制代码

    Patch Code(只是简单跟了下,估计不全只简单跟了下hook createfile的部分,没测试过):
    1. 1.
    2. 004391c9:
    3.      jmp PatchAddr
    4. PatchAddr:
    5.     call PatchFun(00400810)
    6. 恢复原流程:
    7.     mov     ecx, esi
    8.     jmp     004391CB
    9. 2.
    10. 0043B45E  |.  8B07          mov     eax, dword ptr [edi]
    11. 0043B460  |.  48            dec     eax                              ;  Switch (cases 1..C)
    12. 0043B461  |.  83F8 0B       cmp     eax, 0xB
    13. 0043B464  |.  0F87 95020000 ja      0043B6FF

    14. 0043B45E  |.  33C0          xor     eax, eax
    15. 0043B460  |.  40            inc     eax                              ;  Switch (cases 1..C)
    16. 0043B461  |.  83F8 0B       cmp     eax, 0xB
    17. 0043B464  |.  0F87 95020000 ja      0043B6FF
    18. 3.
    19. 00443830   .  6A FF         push    -0x1

    20. 00443830   .  C3            retn
    21. 00443831   ?  90            nop
    复制代码
    ShellcodeBin.rar (1.14 MB, 下载次数: 3)

    评分

    参与人数 1威望 +20 飘云币 +20 收起 理由
    crackvip + 20 + 20 赞一个!

    查看全部评分

    PYG19周年生日快乐!
  • TA的每日心情
    难过
    7 天前
  • 签到天数: 11 天

    [LV.3]偶尔看看II

    发表于 2015-6-14 18:05:17 | 显示全部楼层
    屌炸天,值得学习!
    PYG19周年生日快乐!
  • TA的每日心情
    慵懒
    2023-4-24 08:03
  • 签到天数: 489 天

    [LV.9]以坛为家II

    发表于 2015-6-14 18:36:48 | 显示全部楼层
    QS,你看下400899哪里开始的后面的KEY是怎么处理的

    点评

    你又一眼看到了重点,鄙视你的智商太高了。什么时候带带我  详情 回复 发表于 2015-6-15 12:48
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2015-6-14 22:29:32 | 显示全部楼层
    {:soso_e100:}学习一下!
    PYG19周年生日快乐!
  • TA的每日心情
    难过
    2024-3-10 19:49
  • 签到天数: 473 天

    [LV.9]以坛为家II

    发表于 2015-6-15 12:48:09 | 显示全部楼层
    vipcrack 发表于 2015-6-14 18:36
    QS,你看下400899哪里开始的后面的KEY是怎么处理的

    你又一眼看到了重点,鄙视你的智商太高了。什么时候带带我
    PYG19周年生日快乐!
  • TA的每日心情
    奋斗
    2016-1-13 12:25
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    发表于 2015-6-15 17:10:06 | 显示全部楼层
    不错,你排版的真不错,好舒服,一下就看懂了
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2018-12-31 02:55
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2018-12-31 03:03:13 | 显示全部楼层
    不错的技术分析
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表