脱upx壳踩的一些坑

  练习upx脱壳,该app其实可以直接使用upx.exe -d解压,但是还是想试试看手动脱壳的感觉。踩了两个大坑,留个记录,想必对后来者会有一些帮助。

重建IAT问题

    查找oep还算比较顺利的,在重建IAT时遇到一些问题:

 

 

     如图所示,像这种iat很明显是有问题的,而且观察加载的dll,还有apphelp.dll,这个dll应该是处于兼容性目的存在的,目的是转发api。除了大量的重复的dll之外,还有就是一些错误的数据,比如:

 

 

      这些api应该是来自usp10.dll的,不知道为何放到gdi32.dll上去了。如此种种。后来经过一些研究发现,这可能是兼容性问题造成的。我最初是在Windows11下面脱壳的,所以有这些问题。后来在Windows XP sp3 32bit和Windows 7 64bit下都试过都没有这些烦恼。Windows 10尚未尝试过。

运行时Runtime Error R6002 - Floating point not loaded after unpacking错误

     

 

 

    这个问题看起来像是msvc的实现上的问题,在初始化crt时会检测它所需要的一些数据所在的section是否是只读的,如果不是的话,那么它可能会跳过一些初始化步骤,最终会导致在执行一些crt函数时报上面这个错,比如sprintf之类的。

   这个检查是在内部函数__IsNonwritableInCurrentImage中实现的,通过ida的函数列表并不能找到这个函数,但是我们可以先找到__cinit函数,然后在它的头部可以看到这个函数,双击即可跳转过去了:

 

 

   ; =============== S U B R O U T I N E =======================================
UPX0:005E4910
UPX0:005E4910                               ; Attributes: library function bp-based frame
UPX0:005E4910
UPX0:005E4910                               __IsNonwritableInCurrentImage proc near ; CODE XREF: __cinit+E↑p
UPX0:005E4910                                                                       ; __cinit+79↑p
UPX0:005E4910                                                                       ; SEH_5E4910+FF↑p
UPX0:005E4910                                                                       ; __endthreadex+E↑p
UPX0:005E4910                                                                       ; _threadstartex(x)+6A↑p
UPX0:005E4910
UPX0:005E4910                               ms_exc= CPPEH_RECORD ptr -18h
UPX0:005E4910                               arg_0= dword ptr  8
UPX0:005E4910
UPX0:005E4910                               ; __unwind { // __except_handler4
UPX0:005E4910 55                            push    ebp
UPX0:005E4911 8B EC                         mov     ebp, esp
UPX0:005E4913 6A FE                         push    0FFFFFFFEh
UPX0:005E4915 68 90 79 67 00                push    offset stru_677990
UPX0:005E491A 68 80 F6 5D 00                push    offset __except_handler4
UPX0:005E491F 64 A1 00 00 00 00             mov     eax, large fs:0
UPX0:005E4925 50                            push    eax
UPX0:005E4926 83 EC 08                      sub     esp, 8
UPX0:005E4929 53                            push    ebx
UPX0:005E492A 56                            push    esi
UPX0:005E492B 57                            push    edi
UPX0:005E492C A1 80 58 68 00                mov     eax, ___security_cookie
UPX0:005E4931 31 45 F8                      xor     [ebp+ms_exc.registration.ScopeTable], eax
UPX0:005E4934 33 C5                         xor     eax, ebp
UPX0:005E4936 50                            push    eax
UPX0:005E4937 8D 45 F0                      lea     eax, [ebp+ms_exc.registration]
UPX0:005E493A 64 A3 00 00 00 00             mov     large fs:0, eax
UPX0:005E4940 89 65 E8                      mov     [ebp+ms_exc.old_esp], esp
UPX0:005E4940
UPX0:005E4943                               ;   __try { // __except at loc_5E49AD
UPX0:005E4943 C7 45 FC 00 00 00 00          mov     [ebp+ms_exc.registration.TryLevel], 0
UPX0:005E494A 68 00 00 40 00                push    offset __ImageBase
UPX0:005E494F E8 3C FF FF FF                call    __ValidateImageBase
UPX0:005E494F
UPX0:005E4954 83 C4 04                      add     esp, 4
UPX0:005E4957 85 C0                         test    eax, eax
UPX0:005E4959 74 55                         jz      short loc_5E49B0
UPX0:005E4959
UPX0:005E495B 8B 45 08                      mov     eax, [ebp+arg_0]
UPX0:005E495E 2D 00 00 40 00                sub     eax, offset __ImageBase
UPX0:005E4963 50                            push    eax
UPX0:005E4964 68 00 00 40 00                push    offset __ImageBase
UPX0:005E4969 E8 52 FF FF FF                call    __FindPESection
UPX0:005E4969
UPX0:005E496E 83 C4 08                      add     esp, 8
UPX0:005E4971 85 C0                         test    eax, eax
UPX0:005E4973 74 3B                         jz      short loc_5E49B0
UPX0:005E4973
UPX0:005E4975 8B 40 24                      mov     eax, [eax+24h]
UPX0:005E4978 C1 E8 1F                      shr     eax, 1Fh
UPX0:005E497B F7 D0                         not     eax
UPX0:005E497D 83 E0 01                      and     eax, 1
UPX0:005E497D                               ;   } // starts at 5E4943
UPX0:005E4980 C7 45 FC FE FF FF FF          mov     [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
UPX0:005E4987 8B 4D F0                      mov     ecx, [ebp+ms_exc.registration.Next]
UPX0:005E498A 64 89 0D 00 00 00 00          mov     large fs:0, ecx
UPX0:005E4991 59                            pop     ecx
UPX0:005E4992 5F                            pop     edi
UPX0:005E4993 5E                            pop     esi
UPX0:005E4994 5B                            pop     ebx
UPX0:005E4995 8B E5                         mov     esp, ebp
UPX0:005E4997 5D                            pop     ebp
UPX0:005E4998 C3                            retn
UPX0:005E4998
UPX0:005E4999                               ; ---------------------------------------------------------------------------
UPX0:005E4999
UPX0:005E4999                               loc_5E4999:                             ; DATA XREF: UPX0:stru_677990↓o
UPX0:005E4999                               ;   __except filter // owned by 5E4943
UPX0:005E4999 8B 45 EC                      mov     eax, [ebp+ms_exc.exc_ptr]
UPX0:005E499C 8B 08                         mov     ecx, [eax]
UPX0:005E499E 8B 01                         mov     eax, [ecx]
UPX0:005E49A0 33 D2                         xor     edx, edx
UPX0:005E49A2 3D 05 00 00 C0                cmp     eax, 0C0000005h
UPX0:005E49A7 0F 94 C2                      setz    dl
UPX0:005E49AA 8B C2                         mov     eax, edx
UPX0:005E49AC C3                            retn
UPX0:005E49AC
UPX0:005E49AD                               ; ---------------------------------------------------------------------------
UPX0:005E49AD
UPX0:005E49AD                               loc_5E49AD:                             ; DATA XREF: UPX0:stru_677990↓o
UPX0:005E49AD                               ;   __except(loc_5E4999) // owned by 5E4943
UPX0:005E49AD 8B 65 E8                      mov     esp, [ebp+ms_exc.old_esp]
UPX0:005E49AD
UPX0:005E49B0
UPX0:005E49B0                               loc_5E49B0:                             ; CODE XREF: __IsNonwritableInCurrentImage+49↑j
UPX0:005E49B0                                                                       ; __IsNonwritableInCurrentImage+63↑j
UPX0:005E49B0 C7 45 FC FE FF FF FF          mov     [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
UPX0:005E49B7 33 C0                         xor     eax, eax
UPX0:005E49B9 8B 4D F0                      mov     ecx, [ebp+ms_exc.registration.Next]
UPX0:005E49BC 64 89 0D 00 00 00 00          mov     large fs:0, ecx
UPX0:005E49C3 59                            pop     ecx
UPX0:005E49C4 5F                            pop     edi
UPX0:005E49C5 5E                            pop     esi
UPX0:005E49C6 5B                            pop     ebx
UPX0:005E49C7 8B E5                         mov     esp, ebp
UPX0:005E49C9 5D                            pop     ebp
UPX0:005E49CA C3                            retn
UPX0:005E49CA                               ; } // starts at 5E4910
UPX0:005E49CA
UPX0:005E49CA                               __IsNonwritableInCurrentImage endp

    理论上来说有两种办法可以修复这个错误,一是修改section的权限,让本来应该只读的section变成只读的,但是这有一个问题,因为upx解密后,原来的section可能混在一起了,那么你单纯使用工具去修改pe头中的section权限会导致其它问题。

    我选择第二种方法,直接修改__IsNonwritableInCurrentImage函数,让它总是返回1就可以了,修改前:

UPX0:005E497B F7 D0                         not     eax
UPX0:005E497D 83 E0 01                      and     eax, 1

修改后:

UPX0:005E497B B8 01 00 00 00                mov     eax, 1

     保存,问题解决。

 

posted @ 2022-07-13 16:31  bodong  阅读(320)  评论(0编辑  收藏  举报