kerberos_API_fix

来源:互联网 发布:js怎么设置transform 编辑:程序博客网 时间:2024/06/06 01:18

前言

学脱壳时, 看到人家用kerberos.exe进行目标程序的API Trace.
可以先不上调试器, 看看cm调用的是哪些API(API名称,参数,API的调用地址).
这样就能先确定一些流程点.
还没等资料看完, 就发现这个工具有些问题.
kerberos.exe在x86下好使, 在win7x64下不好使(运行后不打印TraceAPI的日志).
调了一天, 将kerberos.exe的BUG解决了.
这是我第一次正儿八经的在闭源情况下, 在反汇编层面上为第三方程序修复BUG, 解决了还是很开心.
这工具写得早了, 2007年写的, 可能当时还没有win7x64的环境可以测试. 其实不算是作者的BUG. 这软件狠纯真, 没有对抗, 适合用来学习.

修复后的工具下载点

kerberos API spy v1.13 fixed on Win7X64

软件的原理

  • 给出一个要下断点的API配置列表(DllName, ApiName, ApiParameter numbers), 然后根据这个配置单, 对API的头5个字节进行APIHook, 当经过API时, 就能知道API名称, 每个API的参数值, 打印后, 在继续执行API原来的功能.
  • API配置单中的API参数数量, 不是能用软件生产的, 不知道作者当时是不是手工码的:)
  • 主程序(Hook管理程序)在注册表中写入了配置信息, UI上指定要目标程序后, 主程序启动目标程序(挂住的状态),主程序注入DLL到目标程序(注入DLL做完APIHook), 主程序让目标程序继续跑.
  • 由注入的DLL从注册表中配置信息, Hook所有指定的API.
  • 当经过Hook过的API时, 记录日志信息(为了提高效率, 满4KB才写磁盘; 任务完成后, 写最后一次日志).

目标软件的GUG

正常情况 : 在winxp下, 可以记录目标软件调用的API信息.
BUG重新环境 : 在win7x64下, 不能记录目标软件调用的API信息.

软件的BUG原因

发现的BUG有2个

BUG1

建立远线程之前, 要打开目标进程.
OpenProcess时, 要求的权限少了, 原来是0x2A, CreateRemoteThread失败, 错误码C05
改成-1后, CreateRemoteThread成功了. 最合适的权限值没有去试验.
发现这个问题, 还不是先看代码, 是去看目标进程中,是否有Hook后的DLL.
发现没有Dll在目标程序中Hook, 去检查2个点, 是HookDll执行完了, 还是没注入成功.
刚开始以为是HookDll由于逻辑不正确, 执行完了, 结果不是:)
然后才去检查是否Hook成功.

004016D4  |.  FF75 08       push    dword ptr [ebp+8]                ; /ProcessId004016D7  |.  6A 00         push    0                                ; |Inheritable = FALSE004016D9      6A FF         push    -1                               ;  the org value is 0x2a004016DB  |.  E8 D6140000   call    <jmp.&kernel32.OpenProcess>      ; \OpenProcess004016E0  |.  0BC0          or      eax, eax004016E2  |.  75 0A         jnz     short 004016EE004016E4  |.  BA 9F314000   mov     edx, 0040319F                    ;  ASCII "Can't open process"004016E9  |.  E9 AE000000   jmp     0040179C004016EE  |>  8945 E4       mov     dword ptr [ebp-1C], eax004016F1  |.  6A 04         push    4                                ; /flProtect = 4004016F3  |.  68 00100000   push    1000                             ; |flAllocationType = 1000 (4096.)004016F8  |.  FF75 FC       push    dword ptr [ebp-4]                ; |dwSize004016FB  |.  6A 00         push    0                                ; |lpAddress = NULL004016FD  |.  50            push    eax                              ; |hProcess004016FE  |.  E8 BF140000   call    <jmp.&kernel32.VirtualAllocEx>   ; \VirtualAllocEx00401703  |.  0BC0          or      eax, eax00401705  |.  75 0A         jnz     short 0040171100401707  |.  BA B2314000   mov     edx, 004031B2                    ;  ASCII "Can't allocate memory"0040170C  |.  E9 8B000000   jmp     0040179C00401711  |>  8945 E0       mov     dword ptr [ebp-20], eax00401714  |.  6A 00         push    0                                ; /pBytesWritten = NULL00401716  |.  FF75 FC       push    dword ptr [ebp-4]                ; |BytesToWrite00401719  |.  68 28404000   push    00404028                         ; |Buffer = kerberos.004040280040171E  |.  50            push    eax                              ; |Address0040171F  |.  FF75 E4       push    dword ptr [ebp-1C]               ; |hProcess00401722  |.  E8 AD140000   call    <jmp.&kernel32.WriteProcessMemor>; \WriteProcessMemory00401727  |.  0BC0          or      eax, eax00401729  |.  75 07         jnz     short 004017320040172B  |.  BA C8314000   mov     edx, 004031C8                    ;  ASCII "Can't write to process memory"00401730  |.  EB 6A         jmp     short 0040179C00401732  |>  68 2D324000   push    0040322D                         ; /pModule = "kernel32.dll"00401737  |.  E8 62140000   call    <jmp.&kernel32.GetModuleHandleA> ; \GetModuleHandleA0040173C  |.  8945 DC       mov     dword ptr [ebp-24], eax0040173F  |.  68 3A324000   push    0040323A                         ; /ProcNameOrOrdinal = "LoadLibraryA"00401744  |.  50            push    eax                              ; |hModule00401745  |.  E8 5A140000   call    <jmp.&kernel32.GetProcAddress>   ; \GetProcAddress0040174A  |.  0BC0          or      eax, eax0040174C  |.  75 07         jnz     short 004017550040174E  |.  BA E6314000   mov     edx, 004031E6                    ;  ASCII "Can't get procedure address"00401753  |.  EB 47         jmp     short 0040179C00401755  |>  8945 F4       mov     dword ptr [ebp-C], eax00401758  |.  33C9          xor     ecx, ecx0040175A  |.  51            push    ecx                              ; /lpThreadId => NULL0040175B  |.  51            push    ecx                              ; |dwCreationFlags => 00040175C  |.  FF75 E0       push    dword ptr [ebp-20]               ; |lpParameter0040175F  |.  50            push    eax                              ; |lpStartAddress00401760  |.  51            push    ecx                              ; |dwStackSize => 000401761  |.  51            push    ecx                              ; |lpThreadAttributes =>00401762  |.  FF75 E4       push    dword ptr [ebp-1C]               ; |hProcess00401765  |.  E8 16140000   call    <jmp.&kernel32.CreateRemoteThrea>; \CreateRemoteThread0040176A  |.  8945 E8       mov     dword ptr [ebp-18], eax0040176D  |.  6A FF         push    -1                               ; /Timeout = INFINITE0040176F  |.  50            push    eax                              ; |hObject00401770  |.  E8 59140000   call    <jmp.&kernel32.WaitForSingleObje>; \WaitForSingleObject00401775  |.  68 00800000   push    8000                             ; /dwFreeType = 8000 (32768.)0040177A  |.  6A 00         push    0                                ; |dwSize = 00040177C  |.  FF75 E0       push    dword ptr [ebp-20]               ; |lpAddress0040177F  |.  FF75 E4       push    dword ptr [ebp-1C]               ; |hProcess00401782  |.  E8 41140000   call    <jmp.&kernel32.VirtualFreeEx>    ; \VirtualFreeEx00401787  |.  FF75 E8       push    dword ptr [ebp-18]               ; /hObject0040178A  |.  E8 E5130000   call    <jmp.&kernel32.CloseHandle>      ; \CloseHandle0040178F  |.  FF75 E4       push    dword ptr [ebp-1C]               ; /hObject00401792  |.  E8 DD130000   call    <jmp.&kernel32.CloseHandle>      ; \CloseHandle

从反汇编实现看出作者不是狠严谨.
* CreateRemoteThread没有加错误检查, 如果没注入成功, 没有给使用者提示.

BUG2

当给定HookApi的配置文件时, 可以给出Dll中的API名称或API序号.
但是作者疏忽了一点, 如果配置文件中的API在当前环境中没有(e.g. user32.dll’s Win32PoolAllocationStats), 这个API在WinXp下有, 在Win7X64下没有.
作者就将这种不存在的WinAPI当作数字去算API地址, 这算出来肯定错了 . 然后就发生访问异常, 注入的DLL崩掉了, 日志也就记不成了.
这个BUG在代码层面的修复方法:如果不是API名称, 要看是不是API序号, 序号中只有数字的, 如果是字母, 不能算API序号.
从反汇编层面, 我简单的修复了一下, 如果不是API名称, 就不Hook.
因为作者给出的配置文件中, 没有给定API是序号的情况, 估计他自己也没有试验这种情况.

10001595 <ke_core.fnHookApi>            /$  55            push    ebp                              ;  下API钩子10001596                                |.  8BEC          mov     ebp, esp10001598                                |.  83C4 EC       add     esp, -141000159B                                |.  8945 FC       mov     dword ptr [ebp-4], eax1000159E                                |.  895D F0       mov     dword ptr [ebp-10], ebx100015A1                                |.  56            push    esi                              ;  75960000是hDll100015A2                                |.  57            push    edi100015A3                                |.  51            push    ecx100015A4                                |.  57            push    edi                              ; /ProcNameOrOrdinal100015A5                                |.  53            push    ebx                              ; |hModule100015A6                                |.  E8 11110000   call    <jmp.&kernel32.GetProcAddress>   ; \GetProcAddress100015AB                                |.  0BC0          or      eax, eax                         ;  get api addr100015AD                                    74 19         je      short <L_CANT_GET_API_ADDR>100015AF                                    8945 F8       mov     dword ptr [ebp-8], eax100015B2                                    8D4D F4       lea     ecx, dword ptr [ebp-C]100015B5                                |.  51            push    ecx                              ; /pOldProtect100015B6                                |.  6A 40         push    40                               ; |NewProtect = PAGE_EXECUTE_READWRITE100015B8                                |.  68 00100000   push    1000                             ; |Size = 1000 (4096.)100015BD                                |.  50            push    eax                              ; |Address100015BE                                |.  E8 3B110000   call    <jmp.&kernel32.VirtualProtect>   ; \修改函数地址为可读写执行100015C3                                |.  E9 51010000   jmp     10001719100015C8 <ke_core.L_CANT_GET_API_ADDR>      E9 73010000   jmp     <L_FUN_API_HOOK_END>             ;  fnIsFunSn不能再调用100015CD                                    90            nop100015CE                                    90            nop100015CF                                    90            nop100015D0                                    90            nop100015D1                                |.  8945 EC       mov     dword ptr [ebp-14], eax100015D4                                |.  C605 AC560010>mov     byte ptr [100056AC], 0100015DB                                |.  803D B4570010>cmp     byte ptr [100057B4], 0100015E2                                |.  75 20         jnz     short 10001604100015E4                                |.  68 9C540010   push    1000549C100015E9                                |.  68 AC560010   push    100056AC100015EE                                |.  E8 65120000   call    <AppendLen>100015F3                                |.  68 A4550010   push    100055A4100015F8                                |.  68 AC560010   push    100056AC100015FD                                |.  E8 56120000   call    <AppendLen>10001602                                |.  EB 0F         jmp     short 1000161310001604                                |>  68 B4570010   push    100057B410001609                                |.  68 AC560010   push    100056AC1000160E                                |.  E8 45120000   call    <AppendLen>10001613                                |>  8B15 70500010 mov     edx, dword ptr [10005070]10001619                                |.  C602 00       mov     byte ptr [edx], 01000161C                                |.  803F 40       cmp     byte ptr [edi], 401000161F                                |.  75 48         jnz     short 1000166910001621                                |.  FF75 EC       push    dword ptr [ebp-14]10001624                                |.  8F45 F8       pop     dword ptr [ebp-8]10001627                                |.  8D45 F4       lea     eax, dword ptr [ebp-C]1000162A                                |.  50            push    eax                              ; /pOldProtect1000162B                                |.  6A 40         push    40                               ; |NewProtect = PAGE_EXECUTE_READWRITE1000162D                                |.  68 00100000   push    1000                             ; |Size = 1000 (4096.)10001632                                |.  FF75 F8       push    dword ptr [ebp-8]                ; |Address10001635                                |.  E8 C4100000   call    <jmp.&kernel32.VirtualProtect>   ; \VirtualProtect1000163A                                |.  68 AC560010   push    100056AC1000163F                                |.  FF35 70500010 push    dword ptr [10005070]10001645                                |.  E8 0E120000   call    <AppendLen>1000164A                                |.  FF35 70500010 push    dword ptr [10005070]10001650                                |.  E8 CB110000   call    <StrLen>10001655                                |.  8B15 70500010 mov     edx, dword ptr [10005070]1000165B                                |.  03D0          add     edx, eax1000165D                                |.  42            inc     edx1000165E                                |.  8915 14500010 mov     dword ptr [10005014], edx10001664                                |.  E9 B0000000   jmp     1000171910001669                                |>  803F 2B       cmp     byte ptr [edi], 2B1000166C                                |.  75 46         jnz     short 100016B41000166E                                |.  8B45 F0       mov     eax, dword ptr [ebp-10]10001671                                |.  0345 EC       add     eax, dword ptr [ebp-14]10001674                                |.  8945 F8       mov     dword ptr [ebp-8], eax10001677                                |.  8D4D F4       lea     ecx, dword ptr [ebp-C]1000167A                                |.  51            push    ecx                              ; /pOldProtect1000167B                                |.  6A 40         push    40                               ; |NewProtect = PAGE_EXECUTE_READWRITE1000167D                                |.  68 00100000   push    1000                             ; |Size = 1000 (4096.)10001682                                |.  50            push    eax                              ; |Address10001683                                |.  E8 76100000   call    <jmp.&kernel32.VirtualProtect>   ; \VirtualProtect10001688                                |.  68 AC560010   push    100056AC1000168D                                |.  FF35 70500010 push    dword ptr [10005070]10001693                                |.  E8 C0110000   call    <AppendLen>10001698                                |.  FF35 70500010 push    dword ptr [10005070]1000169E                                |.  E8 7D110000   call    <StrLen>100016A3                                |.  8B15 70500010 mov     edx, dword ptr [10005070]100016A9                                |.  03D0          add     edx, eax100016AB                                |.  42            inc     edx100016AC                                |.  8915 14500010 mov     dword ptr [10005014], edx100016B2                                |.  EB 65         jmp     short 10001719100016B4                                |>  803F 23       cmp     byte ptr [edi], 23100016B7                                |.  75 60         jnz     short 10001719100016B9                                |.  FF75 EC       push    dword ptr [ebp-14]               ; /ProcNameOrOrdinal100016BC                                |.  FF75 F0       push    dword ptr [ebp-10]               ; |hModule100016BF                                |.  E8 F80F0000   call    <jmp.&kernel32.GetProcAddress>   ; \GetProcAddress100016C4                                |.  0BC0          or      eax, eax100016C6                                |.  74 40         je      short 10001708100016C8                                |.  8945 F8       mov     dword ptr [ebp-8], eax100016CB                                |.  8D4D F4       lea     ecx, dword ptr [ebp-C]100016CE                                |.  51            push    ecx                              ; /pOldProtect100016CF                                |.  6A 40         push    40                               ; |NewProtect = PAGE_EXECUTE_READWRITE100016D1                                |.  68 00100000   push    1000                             ; |Size = 1000 (4096.)100016D6                                |.  50            push    eax                              ; |Address100016D7                                |.  E8 22100000   call    <jmp.&kernel32.VirtualProtect>   ; \VirtualProtect100016DC                                |.  68 AC560010   push    100056AC100016E1                                |.  FF35 70500010 push    dword ptr [10005070]100016E7                                |.  E8 6C110000   call    <AppendLen>100016EC                                |.  FF35 70500010 push    dword ptr [10005070]100016F2                                |.  E8 29110000   call    <StrLen>100016F7                                |.  8B15 70500010 mov     edx, dword ptr [10005070]100016FD                                |.  03D0          add     edx, eax100016FF                                |.  42            inc     edx10001700                                |.  8915 14500010 mov     dword ptr [10005014], edx10001706                                |.  EB 11         jmp     short 1000171910001708                                |>  33C0          xor     eax, eax1000170A                                |.  8945 F8       mov     dword ptr [ebp-8], eax1000170D                                |.  FF05 04500010 inc     dword ptr [10005004]10001713                                |.  57            push    edi10001714                                |.  E8 F6050000   call    10001D0F10001719                                |>  8B45 FC       mov     eax, dword ptr [ebp-4]1000171C                                |.  E8 82000000   call    <fnGetApiHookInfoPos>            ;  计数10001721                                |.  8B45 F8       mov     eax, dword ptr [ebp-8]10001724                                |.  8942 08       mov     dword ptr [edx+8], eax10001727                                |.  0BC0          or      eax, eax10001729                                |.  74 15         je      short <L_FUN_API_HOOK_END>1000172B                                |.  8B45 FC       mov     eax, dword ptr [ebp-4]           ;  函数不为空1000172E                                |.  E8 82000000   call    <fnApiCnt>10001733                                |.  8B45 F8       mov     eax, dword ptr [ebp-8]10001736                                |.  8B08          mov     ecx, dword ptr [eax]             ;  读API实现头4个个OPCODE10001738                                |.  890A          mov     dword ptr [edx], ecx             ;  保存API实现头4个字节1000173A                                |.  8A48 04       mov     cl, byte ptr [eax+4]1000173D                                |.  884A 04       mov     byte ptr [edx+4], cl10001740 <ke_core.L_FUN_API_HOOK_END>   |>  59            pop     ecx                              ;  保存5个字节中的最后一个.10001741                                |.  5F            pop     edi10001742                                |.  5E            pop     esi10001743                                |.  C9            leave10001744                                \.  C3            retn

调试代码

在开始调试时, 由于HookDll崩溃退出, 需要加调试代码才能附加.
* 在HookDll’s DllMain入口处加0xcc, 会使HookDll崩溃,无法调试附加.
* 加了一段弹框代码, 附加修复完再去掉.

10001040                                /$  55            push    ebp10001041                                |.  8BEC          mov     ebp, esp10001043                                |.  81C4 FCFEFFFF add     esp, -10410001049                                    E9 B2220000   jmp     100033001000104E                                |.  E8 D4100000   call    10002127                         ;  read cfg10001053                                |.  E8 40160000   call    <jmp.&kernel32.GetCurrentProcess>; [GetCurrentProcessId
10003300                                    90            nop10003301                                    90            nop10003302                                    90            nop10003303                                    90            nop10003304                                    90            nop10003305                                    90            nop10003306                                    90            nop10003307                                    90            nop10003308                                    90            nop10003309                                    90            nop1000330A                                    90            nop1000330B                                    90            nop1000330C                                    90            nop1000330D                                    E8 8AEAFFFF   call    10001D9C10003312                                  ^ E9 37DDFFFF   jmp     1000104E

之前的弹框代码

10003300   > \6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL10003302   .  6A 00         push    0                                ; |Title = NULL10003304   .  6A 00         push    0                                ; |Text = NULL10003306   .  6A 00         push    0                                ; |hOwner = NULL10003308   .  E8 6DF3FFFF   call    <jmp.&user32.MessageBoxA>        ; \MessageBoxA1000330D   .  E8 8AEAFFFF   call    10001D9C10003312   .^ E9 37DDFFFF   jmp     1000104E

修复后程序记录的日志

kerberos API spy v1.13(C)2004-2007 Rustem FasihovThu Mar 2 2:47:58 2017DLL's           : 2DLL's failed    : 0Functions       : 1310Functions failed: 0========================================================================================================================================================================================================test.exe     | 00401013 | MessageBoxA(00000000, 00402042: "Run this program under other spyes", 00402036: "Spy testing", 00000000) returns: 00000001test.exe     | 00401018 | IsDebuggerPresent() returns: 00000000test.exe     | 0040102F | MessageBoxA(00000000, 00402023: "NOT under debugger", 00402023: "NOT under debugger", 00000000) returns: 00000001test.exe     | 0040104B | ExitProcess(00000000) ========================================================================================================================================================================================================END OF REPORT
0 0
原创粉丝点击