我不是StackExchange的新手,但我是逆向工程的新手,所以请耐心等待! :P

目前,我正在处理一个可执行文件,我想对其进行一些修改以供个人使用;该应用程序的源代码不可用,因此我只能对其进行修改或尝试。我同时使用IDA Pro 6.1和OllyDBG 2.0作为工具。

准确地说,我想将应用程序可以从500读取到CFG_ENTRY的数量增加到1000方法中显然,在编译时已预先分配了一个静态内存区域:

.text:008F2860 ReadCfgFile     proc near ; DATA XREF: .rdata:0137A1ECo
.text:008F2860 var_20          = dword ptr -20h
.text:008F2860 var_1C          = dword ptr -1Ch
.text:008F2860 var_18          = dword ptr -18h
.text:008F2860 var_C           = dword ptr -0Ch
.text:008F2860 var_4           = dword ptr -4
.text:008F2860 arg_0           = dword ptr  4
.text:008F2860 arg_4           = byte ptr  8
.text:008F2860
.text:008F2860                 push    0FFFFFFFFh
.text:008F2862                 mov     eax, large fs:0
.text:008F2868                 push    offset sub_1288B18
.text:008F286D                 push    eax
.text:008F286E                 mov     large fs:0, esp
.text:008F2875                 sub     esp, 14h
.text:008F2878                 push    ebx
.text:008F2879                 push    ebp
.text:008F287A                 push    esi
.text:008F287B                 push    edi
.text:008F287C                 mov     edi, [esp+30h+arg_0]
.text:008F2880                 mov     eax, [edi+10h]
.text:008F2883                 cmp     eax, [edi+8]
.text:008F2886                 mov     esi, ecx
.text:008F2888                 jnb     loc_8F2930
.text:008F288E                 mov     edi, edi
.text:008F2890
.text:008F2890 loc_8F2890:
.text:008F2890                 mov     eax, [esi+79954h]
.text:008F2896                 cmp     eax, 3E8h
.text:008F289B                 jge     loc_8F29DF
.text:008F28A1                 mov     edx, eax
.text:008F28A3                 shl     edx, 5
.text:008F28A6                 lea     ecx, [eax+1]
.text:008F28A9                 sub     edx, eax
.text:008F28AB                 lea     eax, [eax+edx*8]
.text:008F28AE                 mov     [esi+79954h], ecx
.text:008F28B4                 push    edi
.text:008F28B5                 lea     ecx, [esi+eax*4+4]
.text:008F28B9                 call    ReadEDURecord
.text:008F28BE                 test    al, al
.text:008F28C0                 jz      loc_8F2947
.text:008F28C6                 mov     eax, [esi+79954h]
.text:008F28CC                 mov     ecx, eax
.text:008F28CE                 shl     ecx, 5
.text:008F28D1                 sub     ecx, eax
.text:008F28D3                 lea     edx, [eax+ecx*8]
.text:008F28D6                 mov     ebp, [esi+edx*4-3E0h]
.text:008F28DD                 lea     eax, [esp+30h+arg_0]
.text:008F28E1                 lea     ebx, [esi+79958h]
.text:008F28E7                 push    eax
.text:008F28E8                 mov     ecx, ebx
.text:008F28EA                 mov     [esp+34h+arg_0], ebp
.text:008F28EE                 call    sub_437DF0
.text:008F28F3                 test    eax, eax
.text:008F28F5                 jz      short loc_8F2902
.text:008F28F7                 cmp     [esp+30h+arg_4], 0
.text:008F28FC                 jz      loc_8F2994
.text:008F2902
.text:008F2902 loc_8F2902:
.text:008F2902                 mov     ecx, [esi+79954h]
.text:008F2908                 sub     ecx, 1
.text:008F290B                 lea     edx, [esp+30h+arg_0]
.text:008F290F                 push    edx
.text:008F2910                 lea     eax, [esp+34h+var_20]
.text:008F2914                 mov     [esp+34h+arg_0], ecx
.text:008F2918                 push    eax
.text:008F2919                 mov     ecx, ebx
.text:008F291B                 mov     [esp+38h+var_20], ebp
.text:008F291F                 call    sub_437890
.text:008F2924                 mov     ecx, [edi+10h]
.text:008F2927                 cmp     ecx, [edi+8]
.text:008F292A                 jb      loc_8F2890
.text:008F2930
.text:008F2930 loc_8F2930:
.text:008F2930                 pop     edi
.text:008F2931                 pop     esi
.text:008F2932                 pop     ebp
.text:008F2933                 mov     al, 1
.text:008F2935                 pop     ebx
.text:008F2936                 mov     ecx, [esp+20h+var_C]
.text:008F293A                 mov     large fs:0, ecx
.text:008F2941                 add     esp, 20h
.text:008F2944                 retn    8
.text:008F2947
.text:008F2947 loc_8F2947:
.text:008F2947                 push    0
.text:008F2949                 call    sub_D386E0
.text:008F294E                 add     esp, 4
.text:008F2951                 mov     ecx, edi
.text:008F2953                 mov     esi, eax
.text:008F2955                 call    sub_D4D270
.text:008F295A                 push    eax ; ArgList
.text:008F295B                 push    offset aErrMsg_1 ; Error Message
.text:008F2960                 call    sub_D386E0
.text:008F2965                 add     esp, 8
.text:008F2968                 call    sub_D388C0
.text:008F296D                 lea     edx, [esp+30h+var_20]
.text:008F2971                 push    edx
.text:008F2972                 lea     ecx, [esp+34h+var_18]
.text:008F2976                 mov     [esp+34h+var_20], eax
.text:008F297A                 mov     [esp+34h+var_1C], 640h
.text:008F2982                 call    sub_403D60
.text:008F2987                 mov     [esp+30h+var_4], 0
.text:008F298F                 jmp     loc_8F2A27
.text:008F2994
.text:008F2994 loc_8F2994:
.text:008F2994                 push    0
.text:008F2996                 call    sub_D386E0
.text:008F299B                 add     esp, 4
.text:008F299E                 mov     ecx, edi
.text:008F29A0                 mov     esi, eax
.text:008F29A2                 call    sub_D4D270
.text:008F29A7                 push    eax
.text:008F29A8                 push    ebp             ; ArgList
.text:008F29A9                 push    offset aErrMsg_2 ; Error Message
.text:008F29AE                 call    sub_D386E0
.text:008F29B3                 add     esp, 0Ch
.text:008F29B6                 call    sub_D388C0
.text:008F29BB                 mov     [esp+30h+var_20], eax
.text:008F29BF                 lea     eax, [esp+30h+var_20]
.text:008F29C3                 push    eax
.text:008F29C4                 lea     ecx, [esp+34h+var_18]
.text:008F29C8                 mov     [esp+34h+var_1C], 640h
.text:008F29D0                 call    sub_403D60
.text:008F29D5                 mov     [esp+30h+var_4], 1
.text:008F29DD                 jmp     short loc_8F2A27
.text:008F29DF
.text:008F29DF loc_8F29DF:
.text:008F29DF                 push    0
.text:008F29E1                 call    sub_D386E0
.text:008F29E6                 add     esp, 4
.text:008F29E9                 mov     ecx, edi
.text:008F29EB                 mov     esi, eax
.text:008F29ED                 call    sub_D4D270
.text:008F29F2                 push    eax             ; ArgList
.text:008F29F3                 push    offset aErrMsg_0 ; Error Message
.text:008F29F8                 call    sub_D386E0
.text:008F29FD                 add     esp, 8
.text:008F2A00                 call    sub_D388C0
.text:008F2A05                 lea     ecx, [esp+30h+var_20]
.text:008F2A09                 push    ecx
.text:008F2A0A                 lea     ecx, [esp+34h+var_18]
.text:008F2A0E                 mov     [esp+34h+var_20], eax
.text:008F2A12                 mov     [esp+34h+var_1C], 640h
.text:008F2A1A                 call    sub_403D60
.text:008F2A1F                 mov     [esp+30h+var_4], 2
.text:008F2A27
.text:008F2A27 loc_8F2A27:
.text:008F2A27                 mov     eax, [esp+30h+var_18]
.text:008F2A2B                 test    eax, eax
.text:008F2A2D                 jz      short loc_8F2A3A
.text:008F2A2F                 push    esi
.text:008F2A30                 push    eax
.text:008F2A31                 call    ds:??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char const *)
.text:008F2A37                 add     esp, 8
.text:008F2A3A
.text:008F2A3A loc_8F2A3A:
.text:008F2A3A                 lea     ecx, [esp+30h+var_18]
.text:008F2A3E                 mov     [esp+30h+var_4], 0FFFFFFFFh
.text:008F2A46                 call    sub_403DF0
.text:008F2A4B                 mov     ecx, [esp+30h+var_C]
.text:008F2A4F                 pop     edi
.text:008F2A50                 pop     esi
.text:008F2A51                 pop     ebp
.text:008F2A52                 xor     al, al
.text:008F2A54                 pop     ebx
.text:008F2A55                 mov     large fs:0, ecx
.text:008F2A5C                 add     esp, 20h
.text:008F2A5F                 retn    8
.text:008F2A5F ReadCfgFile     endp


[编辑1-自开始以来我应该知道的一切!]

按照@sealed ...答案的建议,我使用了一个类检查器来检测虚函数表,并找到了完整的类描述符。好吧...实际上,有两个类引用了我的目标方法ReadCfgFile,并且在整个可执行文件中没有直接调用它:继续!是的!]

阅读@Guntram Blohm的答案后,我进行了更多研究,以收集和分析他建议的数据。我做的第一件事是使用PEiD分析可执行文件,这是我从可执行文件中获得的信息:

当我在ReadCfgFile方法上设置断点时,这里这是我从OllyDBG堆栈中获得的内容:

读取它的例程,但没有显式调用ReadCfgFile(突出显示了偏移量):看起来像这样(来自IDA Pro的伪代码):

.rdata:0137A1D4 ; class DATABASE_TABLE<CFG_ENTRY,500,unsigned int> [SI] O: 0, A: 0
.rdata:0137A1D4 dd offset ??_R4?$DATABASE_TABLE@UCFG_ENTRY@@
Compiler: Microsoft Visual C++ 7.0 Method2 [Debug]
Entropy: 6.24 (Not Packed)
Linker Info: 7.10
BPE@I@@6B@ ; RTTI Complete Object Locator .rdata:0137A1D8 ; const DATABASE_TABLE<struct CFG_ENTRY,500,unsigned int> VF Table .rdata:0137A1D8 ??_7?$DATABASE_TABLE@UCFG_ENTRY@@
CPU Stack
Address   Value      ASCII Comments
0018B2C0  [008EE644  D�.  ; RETURN to myapp.008EE644
BPE@I@@6B@ dd offset sub_8EF0F0 ; DATA XREF: sub_8EEFC0+1Do .rdata:0137A1DC dd offset nullsub_648 .rdata:0137A1E0 dd offset sub_8EAB30 .rdata:0137A1E4 dd offset sub_8EF060 .rdata:0137A1E8 dd offset sub_8EE500 .rdata:0137A1EC dd offset ReadCfgFile .rdata:0137A1F0 ; class CFG_DB: DATABASE_TABLE<CFG_ENTRY,500,unsigned int> [SI] O: 0, A: 0 .rdata:0137A1F0 dd offset ??_R4CFG_DB@@6B@ ; RTTI Complete Object Locator .rdata:0137A1F4 ; const CFG_DB VFTable .rdata:0137A1F4 ??_7UNIT_DB@@6B@ dd offset sub_8EF2B0 ; DATA XREF: sub_8EF290+8o .rdata:0137A1F8 dd offset nullsub_648 .rdata:0137A1FC dd offset sub_8EAB30 .rdata:0137A200 dd offset sub_8EF060 .rdata:0137A204 dd offset sub_8EE8B0 .rdata:0137A208 dd offset ReadCfgFile .rdata:0137A20C dd offset sub_8EE5D0


因此,看起来好像正在实例化008EE644的“数组”,该方法调用的是另一个链接到可执行文件的库的方法。它可能有任何帮助:

.text:008EE5D0 sub_8EE5D0      proc near ; CODE XREF: sub_411B20+2CBp
.text:008EE5D0 var_41          = byte ptr -41h
.text:008EE5D0 var_40          = dword ptr -40h
.text:008EE5D0 var_3C          = dword ptr -3Ch
.text:008EE5D0 var_38          = byte ptr -38h
.text:008EE5D0 var_34          = dword ptr -34h
.text:008EE5D0 var_30          = dword ptr -30h
.text:008EE5D0 var_2C          = byte ptr -2Ch
.text:008EE5D0 var_C           = dword ptr -0Ch
.text:008EE5D0 var_4           = dword ptr -4
.text:008EE5D0
.text:008EE5D0                 push    0FFFFFFFFh
.text:008EE5D2                 push    offset SEH_8EE5D0
.text:008EE5D7                 mov     eax, large fs:0
.text:008EE5DD                 push    eax
.text:008EE5DE                 mov     large fs:0, esp
.text:008EE5E5                 sub     esp, 38h
.text:008EE5E8                 push    ebx
.text:008EE5E9                 push    ebp
.text:008EE5EA                 mov     ebx, ecx
.text:008EE5EC                 push    offset aCfgFile ; "application.cfg"
.text:008EE5F1                 mov     [esp+50h+var_30], ebx
.text:008EE5F5                 call    sub_41BD00
.text:008EE5FA                 add     esp, 4
.text:008EE5FD                 push    eax
.text:008EE5FE                 lea     ecx, [esp+50h+var_38]
.text:008EE602                 call    sub_F018E0
.text:008EE607                 xor     ebp, ebp
.text:008EE609                 push    ebp
.text:008EE60A                 lea     eax, [esp+50h+var_38]
.text:008EE60E                 push    eax
.text:008EE60F                 lea     ecx, [esp+54h+var_2C]
.text:008EE613                 mov     [esp+54h+var_4], ebp
.text:008EE617                 call    sub_D50170
.text:008EE61C                 lea     ecx, [esp+4Ch+var_38] ; void *
.text:008EE620                 mov     byte ptr [esp+4Ch+var_4], 2
.text:008EE625                 call    sub_EFFE30
.text:008EE62A                 mov     edx, [ebx]
.text:008EE62C                 mov     ecx, ebx
.text:008EE62E                 mov     [ebx+7A938h], ebp
.text:008EE634                 call    dword ptr [edx+4]
.text:008EE637                 mov     eax, [ebx]
.text:008EE639                 push    ebp
.text:008EE63A                 lea     ecx, [esp+50h+var_2C]
.text:008EE63E                 push    ecx
.text:008EE63F                 mov     ecx, ebx
.text:008EE641                 call    dword ptr [eax+14h]
.text:008EE644 ; ---------------------------------------------------------------------------         
.text:008EE644                 test    al, al ; HERE IS THE STACK REFERENCE
.text:008EE644 ; ---------------------------------------------------------------------------   
.text:008EE646                 jnz     short loc_8EE66C
.text:008EE648                 lea     ecx, [esp+4Ch+var_2C]
.text:008EE64C                 mov     [esp+4Ch+var_4], 0FFFFFFFFh
.text:008EE654                 call    sub_D4BB30
.text:008EE659                 pop     ebp
.text:008EE65A                 xor     al, al
.text:008EE65C                 pop     ebx
.text:008EE65D                 mov     ecx, [esp+44h+var_C]
.text:008EE661                 mov     large fs:0, ecx
.text:008EE668                 add     esp, 44h
.text:008EE66B                 retn
.text:008EE66C
.text:008EE66C loc_8EE66C:
.text:008EE66C                 xor     edx, edx
.text:008EE66E                 or      eax, 0FFFFFFFFh
.text:008EE671                 mov     dword_1986644, edx
.text:008EE677                 mov     dword_1986650, eax
.text:008EE67C                 push    esi
.text:008EE67D                 mov     dword_1986648, edx
.text:008EE683                 mov     dword_1986654, eax
.text:008EE688                 push    edi
.text:008EE689                 mov     dword_198664C, edx
.text:008EE68F                 mov     dword_1986658, eax
.text:008EE694                 xor     edi, edi
.text:008EE696                 cmp     [ebx+79954h], ebp
.text:008EE69C                 jle     loc_8EE727
.text:008EE6A2                 lea     esi, [ebx+40h]
.text:008EE6A5                 jmp     short loc_8EE6B0
.text:008EE6A7                 align 10h
.text:008EE6B0
.text:008EE6B0 loc_8EE6B0:
.text:008EE6B0                 mov     eax, [esi]
.text:008EE6B2                 mov     cx, [esi+92h]
.text:008EE6B9                 lea     eax, ds:1986644h[eax*2]
.text:008EE6C0                 mov     ax, [eax]
.text:008EE6C3                 cmp     ax, cx
.text:008EE6C6                 jnb     short loc_8EE6CA
.text:008EE6C8                 mov     eax, ecx
.text:008EE6CA
.text:008EE6CA loc_8EE6CA:
.text:008EE6CA                 mov     ecx, [esi]
.text:008EE6CC                 mov     word ptr dword_1986644[ecx*2], ax
.text:008EE6D4                 mov     eax, [esi]
.text:008EE6D6                 mov     cx, [esi+92h]
.text:008EE6DD                 lea     eax, ds:1986650h[eax*2]
.text:008EE6E4                 mov     ax, [eax]
.text:008EE6E7                 cmp     ax, cx
.text:008EE6EA                 jb      short loc_8EE6EE
.text:008EE6EC                 mov     eax, ecx
.text:008EE6EE
.text:008EE6EE loc_8EE6EE:
.text:008EE6EE                 mov     edx, [esi]
.text:008EE6F0                 lea     ecx, [esi-3Ch]
.text:008EE6F3                 mov     word ptr dword_1986650[edx*2], ax
.text:008EE6FB                 call    sub_8ED600
.text:008EE700                 push    eax
.text:008EE701                 mov     eax, [ebx+7A938h]
.text:008EE707                 push    eax
.text:008EE708                 call    sub_F1E550
.text:008EE70D                 add     edi, 1
.text:008EE710                 add     esp, 8
.text:008EE713                 mov     [ebx+7A938h], eax
.text:008EE719                 add     esi, 3E4h
.text:008EE71F                 cmp     edi, [ebx+79954h]
.text:008EE725                 jl      short loc_8EE6B0
.text:008EE727
.text:008EE727 loc_8EE727:
.text:008EE727                 xor     esi, esi
.text:008EE729                 cmp     dword_1667290, ebp
.text:008EE72F                 mov     [esp+54h+var_3C], esi
.text:008EE733                 jbe     loc_8EE840
.text:008EE739                 lea     esp, [esp+0]
.text:008EE740
.text:008EE740 loc_8EE740:
.text:008EE740                 cmp     [ebx+79954h], ebp
.text:008EE746                 mov     [esp+54h+var_41], 0
.text:008EE74B                 mov     [esp+54h+var_40], ebp
.text:008EE74F                 mov     [esp+54h+var_34], ebp
.text:008EE753                 jle     loc_8EE7D9
.text:008EE759                 mov     ebp, 1
.text:008EE75E                 mov     ecx, esi
.text:008EE760                 shl     ebp, cl
.text:008EE762                 lea     edi, [ebx+3B0h]
.text:008EE768
.text:008EE768 loc_8EE768:
.text:008EE768                 cmp     [esp+54h+var_41], 0
.text:008EE76D                 jnz     short loc_8EE77F
.text:008EE76F                 test    [edi-2Ch], ebp
.text:008EE772                 jz      short loc_8EE77F
.text:008EE774                 test    byte ptr [edi+3], 20h
.text:008EE778                 jz      short loc_8EE77F
.text:008EE77A                 mov     [esp+54h+var_41], 1
.text:008EE77F
.text:008EE77F loc_8EE77F: 
.text:008EE77F                 xor     esi, esi
.text:008EE781                 xor     eax, eax
.text:008EE783
.text:008EE783 loc_8EE783:
.text:008EE783                 mov     ecx, [edi-24h]
.text:008EE786                 test    [eax+ecx], ebp
.text:008EE789                 jz      short loc_8EE7AF
.text:008EE78B                 cmp     eax, 10h
.text:008EE78E                 jnb     loc_8EE89B
.text:008EE794                 mov     ecx, esi
.text:008EE796                 shr     ecx, 5
.text:008EE799                 lea     edx, [esp+ecx*4+54h+var_40]
.text:008EE79D                 mov     ecx, esi
.text:008EE79F                 and     ecx, 1Fh
.text:008EE7A2                 mov     ebx, 1
.text:008EE7A7                 shl     ebx, cl
.text:008EE7A9                 or      [edx], ebx
.text:008EE7AB                 mov     ebx, [esp+54h+var_30]
.text:008EE7AF
.text:008EE7AF loc_8EE7AF:
.text:008EE7AF                 add     eax, 4
.text:008EE7B2                 add     esi, 1
.text:008EE7B5                 cmp     eax, 10h
.text:008EE7B8                 jb      short loc_8EE783
.text:008EE7BA                 mov     eax, [esp+54h+var_34]
.text:008EE7BE                 add     eax, 1
.text:008EE7C1                 add     edi, 3E4h
.text:008EE7C7                 cmp     eax, [ebx+79954h]
.text:008EE7CD                 mov     [esp+54h+var_34], eax
.text:008EE7D1                 jl      short loc_8EE768
.text:008EE7D3                 mov     esi, [esp+54h+var_3C]
.text:008EE7D7                 xor     ebp, ebp
.text:008EE7D9
.text:008EE7D9 loc_8EE7D9:
.text:008EE7D9                 push    esi
.text:008EE7DA                 call    sub_8D1490
.text:008EE7DF                 mov     edi, eax
.text:008EE7E1                 add     esp, 4
.text:008EE7E4                 cmp     byte ptr [edi+0BCh], 0
.text:008EE7EB                 jz      short loc_8EE82D
.text:008EE7ED                 xor     esi, esi
.text:008EE7EF                 cmp     esi, 4
.text:008EE7F2                 jnb     loc_8EE8A4
.text:008EE7F8
.text:008EE7F8 loc_8EE7F8:
.text:008EE7F8                 mov     ecx, esi
.text:008EE7FA                 and     ecx, 1Fh
.text:008EE7FD                 mov     edx, 1
.text:008EE802                 shl     edx, cl
.text:008EE804                 mov     ecx, esi
.text:008EE806                 shr     ecx, 5
.text:008EE809                 add     ecx, ecx
.text:008EE80B                 add     ecx, ecx
.text:008EE80D                 test    [esp+ecx+54h+var_40], edx
.text:008EE811                 setnz   al
.text:008EE814                 test    al, al
.text:008EE816                 jnz     short loc_8EE821
.text:008EE818                 not     edx
.text:008EE81A                 and     [ecx+edi+0C0h], edx
.text:008EE821
.text:008EE821 loc_8EE821:
.text:008EE821                 add     esi, 1
.text:008EE824                 cmp     esi, 4
.text:008EE827                 jb      short loc_8EE7F8
.text:008EE829                 mov     esi, [esp+54h+var_3C]
.text:008EE82D
.text:008EE82D loc_8EE82D:
.text:008EE82D                 add     esi, 1
.text:008EE830                 cmp     esi, dword_1667290
.text:008EE836                 mov     [esp+54h+var_3C], esi
.text:008EE83A                 jb      loc_8EE740
.text:008EE840
.text:008EE840 loc_8EE840:
.text:008EE840                 xor     esi, esi
.text:008EE842                 cmp     [ebx+79954h], ebp
.text:008EE848                 jle     short loc_8EE875
.text:008EE84A                 lea     edi, [ebx+108h]
.text:008EE850
.text:008EE850 loc_8EE850:
.text:008EE850                 mov     eax, [edi]
.text:008EE852                 mov     ecx, dword_16E9DC8
.text:008EE858                 push    eax ; Str2
.text:008EE859                 add     ecx, 84h
.text:008EE85F                 call    sub_10E86C0
.text:008EE864                 add     esi, 1
.text:008EE867                 add     edi, 3E4h
.text:008EE86D                 cmp     esi, [ebx+79954h]
.text:008EE873                 jl      short loc_8EE850
.text:008EE875
.text:008EE875 loc_8EE875:
.text:008EE875                 lea     ecx, [esp+54h+var_2C]
.text:008EE879                 mov     [esp+54h+var_4], 0FFFFFFFFh
.text:008EE881                 call    sub_D4BB30
.text:008EE886                 mov     ecx, [esp+54h+var_C]
.text:008EE88A                 pop     edi
.text:008EE88B                 pop     esi
.text:008EE88C                 pop     ebp
.text:008EE88D                 mov     al, 1
.text:008EE88F                 pop     ebx
.text:008EE890                 mov     large fs:0, ecx
.text:008EE897                 add     esp, 44h
.text:008EE89A                 retn
.text:008EE89B
.text:008EE89B loc_8EE89B:
.text:008EE89B                 lea     ecx, [esp+54h+var_40]
.text:008EE89F                 jmp     sub_8D0FE0
.text:008EE8A4
.text:008EE8A4 loc_8EE8A4:
.text:008EE8A4                 lea     ecx, [esp+54h+var_40]
.text:008EE8A8                 jmp     sub_8D0FE0
.text:008EE8A8 sub_8EE5D0      endp


然后跟随地址ReadCfgFile我偶然发现了这个: />对我来说似乎是死路一条...

评论

我在您的反汇编中没有看到对静态缓冲区的任何引用。反汇编中对等效s_CfgEntries的引用在哪里?

嗯,正如我所说,我并不是反汇编专家,我编写的代码只是一个伪代码,用以了解ASM在人类可读代码中的样子。我也看不到任何静态缓冲区,但仅在此处调用了方法ReadCfgFile:“。rdata:0137A1EC dd偏移量ReadCfgFile”,“。rdata:0137A208 dd偏移量ReadCfgFile”。

#1 楼

在我看来,这个问题比您描述的要糟一些,并且没有轻松的方法来解决它。您的编译器在ecx中传递类指针,因为这是使

.text:008F28B5                 lea     ecx, [esi+eax*4+4]
.text:008F28B9                 call    ReadCfgEntry


有意义的唯一方法-其他参数被压入堆栈,而eax的值edx和ebx似乎没有什么意义,因此编译器没有使用某种寄存器中的参数fastcall abi。

现在,让我从循环开始到调用重新排序语句一点(不改变含义,只是为了使事情更清楚一点)。编译器在其他指令之间传播“一个指令增加计数”,这可能是为了利用处理器内的流水线操作:

-- get the current "number of config entries" count, and abort the loop if it exceeds 500

.text:008F2890                 mov     eax, [esi+79954h]
.text:008F2896                 cmp     eax, 1F4h
.text:008F289B                 jge     loc_8F29DF

-- increment the count by one

.text:008F28A6                 lea     ecx, [eax+1]
.text:008F28AE                 mov     [esi+79954h], ecx

-- eax = (( count << 5 - count ) * 8 ) + count = count*249
.text:008F28A1                 mov     edx, eax
.text:008F28A3                 shl     edx, 5
.text:008F28A9                 sub     edx, eax
.text:008F28AB                 lea     eax, [eax+edx*8]

-- push edi, which is a parameter to this function, on the stack;
-- pass this = esi+4*eax+4  == esi+996*count+4 in ecx. Remember esi was set to
-- `this`=`ecx` at the start of the current method and hasn't been changed.

.text:008F28B4                 push    edi
.text:008F28B5                 lea     ecx, [esi+eax*4+4]
.text:008F28B9                 call    ReadCfgEntry


这似乎是ReadCfgEntry是一个类方法,以及在cx中获取其this指针的方法。从计算数组索引的方式来看,我假设原始的C ++类看起来像这样:

class Configuration {
    int whatever;
    ConfigurationEntry entries[500];
    ....
}


,其中ConfigurationEntry是一个996字节的类。现在,坏消息是:这两个类成员需要4+(500 * 996)字节。这等于498004或0x79954。因此,您的条目计数直接位于条目0x79954的后面,另一个变量位于0x79958:

class Configuration {
    int whatever;
    ConfigurationEntry entries[500];
    int entryCount;
    int somethingelse;
    ... ??? ...
}


现在,如果条目是指针并分配给new,只需将新参数的size参数从500修改为1000会更容易。但是,根据您的情况,您必须修改Configuration类的新方法,并且必须修改对“后面的变量”的所有引用。以及配置条目。您已经提到过,偏移量为0x79954的count变量,偏移量为0x79958的下一个变量,但是在阅读器函数中可能有更多未引用的变量,因此很难找到所有变量。


当我看到您对问题的编辑时,我正要发布此内容。

您在编辑中意识到,您需要更改对要在条目数组后面的结构组件的所有访问权限增加。您需要在类方法中执行此操作(使用vtable可以很容易找到它),但在程序的其余部分中也需要执行此操作(因为您不知道哪些原始类变量中的哪些是公共变量,可以从中访问在课程本身之外)。不幸的是,您无法真正实现自动化,因为每次出现0x79954时,您都必须检查它是否是您班级的索引或其他内容。

因为我不这样做我不知道是用哪个编译器来编写程序的,我不能说太多关于它如何存储函数vtable的信息。幸运的是,第一个条目(我之前称为whatever的条目)是vtable指针。如果使用调试器运行该程序,则可以检查它,并在whatever变量到达ReadConfigFile方法时检查它是否指向vtable。如果这样做的话,那就很好了,因为在扩展结构时我们不必担心覆盖vtable。由于您似乎有一个名为DATABASE_TABLE的类和一个派生的名为CFG_DB的类,因此第二个类可能更大。尝试查找第二个较大类的初始化方法。它应该调用new或类似的内存分配器,其大小适合结构大小(因此它可能在79960h和79a00h之间),并且应该将vtable指针移到新分配的内存中,这样您就可以找到它检查vtable的交叉引用。或者,使用调试器并在ReadConfigFile上设置一个断点,然后检查堆栈中调用它的内容,找到一个首先分配该类实例的函数,然后调用其ReadConfigFile成员函数的机会应该就不错了。找到类实例化的位置后,我可能会尝试不将数组大小从500增加到1000,而是在结构后面分配更大的数组。例如,如果您当前的函数分配了79a00h字节,请向其添加1000个条目所需的996000d字节,即16cca0h字节。然后,将ReadCfgEntry前面的

lea ecx, [esi+eax*4+4]


更改为

lea ecx, [esi+eax*4+16cca0h]


这样,您已经创建了当前结构后面的另一个数组,而不是扩展当前结构。这意味着除了配置项本身之外,您的所有结构偏移都没有发生变化。 />,并在下一步中,我们必须重新编写对entries的所有访问,以使用newentries。最简单的方法可能是


用调试器启动程序
在您先前确定的函数上设置一个断点,该断点将在结构之后分配结构。分配结构,在(结构地址+ 4)上设置硬件断点
继续执行程序,每当碰到硬件断点时,您就会找到匹配项

,因为硬件断点位于条目[0],每次访问条目的机会在某个时候都达到其0的机会。只是为每个条目分配一个类实例的地方-像

class Configuration {
    int whatever;
    ConfigurationEntry entries[500];
    int entryCount;
    int somethingelse;
    ... ??? ...
    ConfigurationEntry newEntries[1000];
}


您的硬件断点应很快捕获此循环。修补可执行文件以将500更改为1000,并将entrys [i]计算更改为新数组。之后,新数组将被初始化,而旧数组将仅保留NULL指针。这意味着,将来您可能会通过这些NULL指针获得无效的内存访问权限,这也有助于标识对原始数组的访问(可以修补)。


编辑-之后进行编辑阅读OP的第二个答案

死胡同?根本没有,您收集并发布了非常有价值的信息。首先,您对CFG_DB构造函数的伪代码类结构开头的字节实际上是指向该类的虚函数表的指针。

其次,您的代码段

for (i=0; i<500; i++) {
    entries[i]=new ConfigurationEntry()
}


非常适合(再次,我对汇编说明进行了重新排序,但不会改变它们的功能,但是使它们更易于理解。还记得您的vtable包含函数偏移,nullsub,3个其他函数偏移以及ReadCfgFile作为其条目吗?由于每个都有4个字节,因此vtable中ReadCfgFile函数指针的偏移量为20或14h。在该代码段中,ebx是一个类指针; mov eax, [ebx]从类指针获取vtable指针,而call dword ptr [eax+14h]在该偏移量处调用函数,即ReadCfgFile。在此之前,它将this寄存器(ecx)初始化为ebx,并将2个参数压入堆栈。这似乎是对类方法的非常标准的调用。

接下来,您的构造函数以

void __thiscall sub_8EEFC0(void *this)
{
  void *v1 = this; // esi@1
  *(_DWORD *)this = &DATABASE_TABLE<CFG_ENTRY_500_unsigned_int>::_vftable_;


结尾第一个参数(v1 + 4)是Configuration类中的ConfigurationEntries数组的地址(我保持旧的发明的变量/类名),第二个参数(0x3e4 == 996)每个数组条目的大小;第三(500)个条目的数量,以及一个回调函数。我几乎可以确定这是各个ConfigurationEntries的构造函数。这意味着我需要找到该函数,并且应将其更改为

.text:008EE639                 push    ebp
.text:008EE63A                 lea     ecx, [esp+50h+var_2C]
.text:008EE63E                 push    ecx
.text:008EE63F                 mov     ecx, ebx
.text:008EE637                 mov     eax, [ebx]
.text:008EE641                 call    dword ptr [eax+14h]
.text:008EE644 ;     ---------------------------------------------------------------------------         
.text:008EE644                 test    al, al ; HERE IS THE STACK REFERENCE


,一旦我们为空间分配了空间,XXXXX是newEntries数组的偏移

接下来,在间接调用ReadConfigFile之前重新考虑一部分代码片段,

unknown_libname_2673((char *)v1 + 4, 0x3E4u, 500, sub_8EEA00);


我们看到有一个动作到ebx+7A938h,其中ebx是类指针,因此在此偏移量处似乎还有另一个类成员。元素数量偏移后(79954h),这是很多内存-因此结构具有更多的组件。好消息是您并没有试图将它们全部转移。访问this+502036this+0x7a914的构造函数可能是对此的另一个提示。 (它也访问this+124503,但是this是dword指针,这意味着498012字节,仍然小于502036)。 。连同XREF和数据定义一起,这意味着:

该地址处的类结构不是动态分配的,并且它没有初始化为任何东西,而是一个未初始化的全局变量。在C ++中,它可能是一个

unknown_libname_2673((char *)v1 + XXXXX, 0x3E4u, 1000, sub_8EEA00);


,您看到的所有外部参照都是对myConfig的引用。因为在这些地方的组装说明是

.text:008EE62A                 mov     edx, [ebx]
.text:008EE62C                 mov     ecx, ebx
.text:008EE62E                 mov     [ebx+7A938h], ebp
.text:008EE634                 call    dword ptr [edx+4]


我几乎可以肯定,对这些成员函数的调用在每条指令之后是一条或两条指令。顺便说一句,您刚刚找到了一种捕获许多访问配置的实例的方法。为了验证这一点,unk_190BD08是配置的全局变量,您可以在构造函数(sub_8EEFC0)上使用断点运行程序,我敢打赌它只会被调用一次,而190BD08是它的参数。 />关于配置类实例是静态变量而不是实例化的new()的坏事是,我们不能仅仅增加new()调用的大小。相反,我们必须将其移动到地址空间的一部分,在当前未初始化的数据段的末尾,它不会干扰其他任何内容。在数据段中找到最后一个条目,然后在其后面选择一个合适的地址,然后将unk_190BD08的所有外部参照重写为该新地址。然后,使用ollydbg运行程序,以防万一,在190BD08上放置一个硬件断点,并检查您知道是类成员函数的函数以及已初始化的函数是否都获得了新地址而不是190BD08作为其ecx(此)参数。完成后,您就可以实现第二部分了,将对this+4的访问权限更改为this+XXXX,将XXXX作为类的大小。

我们缺少了new()调用用于Configuration变量意味着我们无法使用其参数来获取类大小。但是我们已经知道类的大小至少为7A938h,因此静态变量占用的地址空间从0x190BD08到至少0x1986640。幸运的是,您的.data段具有该unk_190BD08标签,下一个标签位于0x1986640之后的某个地址,因此下一个标签是其他某个变量,并且两个标签之间的差额为Configuration实例的大小。

剩下要做的一件事-当您将配置变量移到其他所有内容之后时,还必须增加PE文件中该数据段的大小。不幸的是,我不是Windows PE文件格式的熟练者,所以我必须自己做很多研究以正确地做到这一点,所以也许您很幸运,并且还有其他人在此方面比我有,可以为您提供帮助。


编辑-编辑评论的答案


我如何计算CFG_DB类的大小为了在其末尾添加内容?

原始的C ++程序将具有类似

.data:0190BD08 unk_190BD08     db    ? 


(以int为例) ,数据类型可以是任何类型)。
编译器应将所有这些变量放入.data段的未初始化部分。对变量之一的任何访问都将使IDA在该内存地址创建一个标签,并在其访问位置处使用XREF。因此,如果您的.data转储看起来像这样

static Configuration myConfig;


,并且您知道0190BD08是globalConfig,那么01986670是athirdvariable,并且globalConfig的大小是0x01986670-0x0190BD08 = 0x7a968 = 502120字节。

这不是100%可靠的方法,因为如果有任何东西访问globalConfig.somemember,并且某成员的结构偏移为500000(= 0x7a120),则IDA将生成标签以及0x190BD08 + 0x7a120 = 0x1985E28 as的XREF。但是幸运的是,程序的“其余部分”将仅使用globalConfig变量作为成员函数的参数,该成员函数是间接引用,因此IDA不会使用它们创建标签。


如果其他类/方法/等与此修改过的类进行交互,会发生什么?

如果他们访问除500个单独的配置条目以外的任何内容,那么什么都没有,因为这些都没有更改其偏移量。当他们访问条目时,可能会很危险,因为这些访问应重写为newEntries。您必须找出它们的位置(如果幸运的话,这只是在成员函数中),然后在那儿修补代码。 (旧)条目[0]地址(在您的情况下为0x190BD0C,结构开头+ 4)上的硬件断点应对此有所帮助,因为可能访问任何条目的任何内容也可能访问条目[0] 。因此,如果您遇到了硬件断点,例如mov eax, [ebx+4],那么您知道ebx+4正在访问旧地址,应该将其重写为mov eax, [ebx+XXXXX]以使用新阵列。 •创建一个覆盖整个结构的硬件断点以捕获任何访问。那就是空指针异常发生的地方。如果在更改之后,您的程序在正常情况下不抛出NPE,则可能是因为“某物”访问了旧数组,该数组现在只包含NULL,而不是新数组。 。在调试器中捕获NPE,并检查导致该NPE的反汇编/调用堆栈,应该使您了解从旧数组读取NULL指针的位置,因此您知道要更改的指令指向新的。 br />

评论


感谢您的非常非常宝贵的答案。我用模式信息编辑了答案,这可能会对比我更熟练的人有所帮助...

–萨拉索斯
14年5月8日在16:38

更新了我的答案,也回复了您的第二编辑。

–贡特拉姆·布洛姆(Guntram Blohm)
2014年5月8日18:32

@guntram我没有消化答案,但是在您的建议中,如果可以在可执行文件的末尾而不是在某个部分的末尾添加空间,可以很容易地添加空间,甚至还有实用程序可以自动为您执行此操作,并且可以在末尾添加任意数量的空间iirc santmants ZeroAdd是一个这样的实用程序(自从我使用它以来已经很长时间了,但是应该在woodmanns工具仓库中可用

– blabb
2014年5月8日19:22



哇@GuntramBlohm,您的回答真是太神奇了。如果没有您的帮助,我将永远找不到!因此,事实上,要恢复一点,我必须:1)将所有XRef移至unk_190BD08到我的数据空间的底部,以避免覆盖2)将500更改为1000,将“ v1 + 4”更改为新的CFG_ENTRY []构造函数中unknown_libname_2673的调用中的地址但是,我仍然不了解两件事:如何计算CFG_DB类的大小,以便在其末尾添加内容?而且...如果其他类/方法/等与此修改过的类进行交互会发生什么?

–萨拉索斯
2014年5月8日20:34

似乎某处某处正在直接访问globalConfig.entries。这将使IDA在其中放置标签以及外部参照。

–贡特拉姆·布洛姆(Guntram Blohm)
2014年5月10日在18:23

#2 楼

因为我不知道ReadCfgEntry的原型和代码的结构,所以我的答案是不正确的。作为初始化的寄存器:

.text:008F2886                 mov     esi, ecx


它是一个类函数,因此所有者类具有一个初始化目标缓冲区的构造函数。您必须跟踪缓冲区并增加分配大小。

这不是查找构造函数的确切方法;但是一种有效的方法是在函数启动时通过跟踪ECX查找虚拟功能表。大多数情况下,目标缓冲区的第一个元素中包含VFTable。通过XRef在IDA中对其进行引用(如您所做的那样)。 “ .rdata:0137A1EC dd偏移量
ReadCfgFile” ...




找到VFTable之后,大多数时候构造函数是最高成员。

第二:如果缓冲区是静态分配的

如前所述,该函数是类的成员,因此如果您更改感兴趣的指针,则该函数是类的成员。

if (!ReadCfgEntry((void*)(pointer + (996 * entriesCount) + 4), v5))

您应该插入一个存根以分配适当的内存,并将其分配给类。

最后:如果该程序是封闭源代码,这意味着开发人员不喜欢其他人对其进行修改以供个人使用...请确保未违反许可证!

评论


我正在编辑此应用程序仅供个人使用,不会造成伤害,也不会公开发布这些修改……它只是一个非常老的应用程序,不再开发中,但是对于我。同时,我在编辑问题时添加了最近的发现,因此现在您可能会更清楚地了解所有内容。

–萨拉索斯
2014年5月8日在12:31