我在 .rdata 中找不到引用的文本字符串

逆向工程 艾达
2021-06-13 07:29:43

我正在尝试反汇编一个应用程序(由一家中国公司用英文构建)。

我找到了我想要的文本字符串:

.data:0041048C aEraseError     db 'Erase error !',0Ah,0 ; DATA XREF:
.rdata:0040C624o
.data:0041048C                                         ; .rdata:0040CF28o ...

但是,我无法在代码中的任何地方找到它。奇怪的是,找到了一些文本字符串,而其他的则没有。

仅供参考:该应用程序还会加载自定义.dll文件。文本位于主 exe 文件的.rdata段中,但我在代码中看不到它。我尝试过其他反汇编程序,但我使用的是 IDA。

1个回答

您的字符串似乎有一个来自0040C624. 这个字符串可能只是错误字符串数组中的一个条目,数组本身就在0040C624. 您的原始源代码可能如下所示:

char *unused="unused string";
char *errors[] = {
    "error 0",
    "some other error",
    "yet another error",
    "Erase error!",
    "....",
};

void print_error_message(int index) {
    puts(errors[index]);
}

int handle_erase_error() {
    print_error_message(3);
}

如果你编译它(我在 linux 上使用了 gnu C,gcc -m32 xref.c)并将目标代码加载到 IDA,它变成(省略了不相关的部分):

.text:08000000 print_error_message proc near           ; CODE XREF: handle_erase_error+Dp
.text:08000000                 push    ebp
.text:08000001                 mov     ebp, esp
.text:08000003                 sub     esp, 18h
.text:08000006                 mov     eax, [ebp+8]
.text:08000009                 mov     eax, errors[eax*4]
.text:08000010                 mov     [esp], eax      ; s
.text:08000013                 call    puts
.text:08000018                 leave
.text:08000019                 retn
.text:08000019 print_error_message endp


.data:08000030 unused          dd offset aUnusedString ; "unused string"
.data:08000034 errors          dd offset aError0       ; DATA XREF: print_error_message+9r
.data:08000034                                         ; "error 0"
.data:08000038                 dd offset aSomeOtherError ; "some other error"
.data:0800003C                 dd offset aYetAnotherErro ; "yet another error"
.data:08000040                 dd offset aEraseError   ; "Erase error!"
.data:08000044                 dd offset a____         ; "...."

.rodata:08000049 aUnusedString   db 'unused string',0    ; DATA XREF: .data:unusedo
.rodata:08000057 aError0         db 'error 0',0          ; DATA XREF: .data:errorso
.rodata:0800005F aSomeOtherError db 'some other error',0 ; DATA XREF: .data:08000038o
.rodata:08000070 aYetAnotherErro db 'yet another error',0 ; DATA XREF: .data:0800003Co
.rodata:08000082 aEraseError     db 'Erase error!',0     ; DATA XREF: .data:08000040o
.rodata:0800008F a____           db '....',0             ; DATA XREF: .data:08000044o

您会看到每个字符串在该data部分中都有一个指针条目,以及rodata(只读数据)部分中的 ascii 数据并且每个 ascii 字符串都有一个指向指向它的指针的外部参照(交叉引用)——这不是二进制文件的一部分;ida 检测每个字符串的引用位置,并生成“反向引用”或外部参照。

重要的是:0x08000034如果您只有 ascii 字节,您可以使用它来查找字符串表(错误, at )。您可以通过查看其外部参照来找到字符串表本身的使用位置 - 从 print_error_message 函数。相比之下,未使用的串并不会有外部参照,因为它没有任何地方使用。

Ida 将允许您双击外部参照以移动到它“来自”的位置以轻松导航。

我会检查你是否有一个字符串数组,它在你的字符串的外部参照之前开始,它在哪里被使用,以及可能在哪里调用 using 函数。


另一种可能性是我几天前在 ARM android 共享库中看到的。该库有一些字符串保存函数名称,直接在彼此之后,像这样(转换为 x86 语法)

errmsg    db 'Error in %s, file %s, line %d\n', 0
strtab    db 'opencachefile', 0
          db 'closecachefile', 0
          db 'getcacheentry', 0
          db 'putcacheentry', 0
          db 'delcacheentry', 0

从缓存中获取某些内容的函数使用这些字符串中的第三个来记录可能的错误。代码看起来像这样(再次从 arm 转换为 x86):

...
mov    eax, offset strtab
add    eax, 29           ;<-- difference in bytes between 'open' and 'get'
push   eax
mov    eax, offset errmsg
push   eax
call   android_log_print

其他函数具有相似的构造,因此strtab被引用了 5 次(每个函数中一次),并且在每个函数中调整了字节差异。我真的不知道为什么编译器会这样做,但也许您的代码中发生了类似的事情。