在已编译的可执行文件中查找字符串

时间:2011-04-01 10:42:53

标签: c string

我有一个非常简单的程序如下:     #include

int main(){
char* mystring = "ABCDEFGHIJKLMNO";
puts(mystring);

char otherstring[15];
otherstring[0]  = 'a';
otherstring[1]  = 'b';
otherstring[2]  = 'c';
otherstring[3]  = 'd';
otherstring[4]  = 'e';
otherstring[5]  = 'f';
otherstring[6]  = 'g';
otherstring[7]  = 'h';
otherstring[8]  = 'i';
otherstring[9]  = 'j';
otherstring[10] = 'k';
otherstring[11] = 'l';
otherstring[12] = 'm';
otherstring[13] = 'n';
otherstring[14] = 'o';
puts(otherstring);

return 0;
}

编译器是MS VC ++。

无论是否使用优化构建此程序,我都可以使用十六进制编辑器在可执行文件中找到字符串“ABCDEFGHIJKLMNO”。

但是,我找不到字符串“abcdefghijklmno”

编译器执行的操作对于其他字符串有什么不同?

我使用的十六进制编辑器是Hexedit - 但尝试了其他人但仍然找不到其他字符串。任何想法为什么没有或如何找到?

顺便说一句,我不是出于黑客的原因这样做的。

3 个答案:

答案 0 :(得分:5)

这是我的gcc使用此代码所做的事情。我假设您的编译器做了类似的事情。字符串常量存储在只读部分,mystring用它的地址初始化 各个字符直接放在堆栈中的数组位置。另请注意,当您使用它调用puts时,otherstring不会以NULL结尾。

           .file   "test.c"
            .section        .rodata
    .LC0:
            .string "ABCDEFGHIJKLMNO"
            .text
    .globl main
            .type   main, @function
    main:
    .LFB0:
            .cfi_startproc
            pushq   %rbp
                .cfi_def_cfa_offset 16
            movq    %rsp, %rbp
            .cfi_offset 6, -16
            .cfi_def_cfa_register 6
            subq    $48, %rsp
            movq    %fs:40, %rax
            movq    %rax, -8(%rbp)
            xorl    %eax, %eax
    /* here is where mystring is loaded with the address of "ABCDEFGHIJKLMNO" */
            movq    $.LC0, -40(%rbp)
    /* this is the call to puts */
                movq    -40(%rbp), %rax
            movq    %rax, %rdi
            call    puts
    /* here is where the bytes are loaded into otherstring on the stack */            
            movb    $97, -32(%rbp)  //'a'
            movb    $98, -31(%rbp)  //'b'
            movb    $99, -30(%rbp)  //'c'
            movb    $100, -29(%rbp) //'d'
            movb    $101, -28(%rbp) //'e'
            movb    $102, -27(%rbp) //'f'
            movb    $103, -26(%rbp) //'g'
            movb    $104, -25(%rbp) //'h'
            movb    $105, -24(%rbp) //'i'
            movb    $106, -23(%rbp) //'j'
            movb    $107, -22(%rbp) //'k'
            movb    $108, -21(%rbp) //'l'
            movb    $109, -20(%rbp) //'m'
            movb    $110, -19(%rbp) //'n'
            movb    $111, -18(%rbp) //'o'

答案 1 :(得分:1)

编译器可能会将每个字符的编号放入每个数组位置,就像您编写它一样,而不会在读取代码时找到任何优化。请记住,单个字符与c中的数字没有区别,因此您甚至可以使用ascii代码而不是“a”。从一个hexeditor我希望你会看到那些转换回字母,只是间隔一点。

答案 2 :(得分:1)

在第一种情况下,编译器使用完全字符串“ABC ...”初始化数据。

在第二种情况下,每个赋值都是按顺序完成的,因此编译器会生成代码以执行此赋值。在可执行文件中,您应该看到15个重复的字节序列,其中只有初始化程序('a','b','c'...)发生变化。