Search code examples
c++reverse-engineeringhardening

Get literals from C++ binary


After compiling the C++ code

int main(void)
{
    const char * c = "abcdefghijklmnopqrstuvwxyz";
    int a = 1234567890;
    float tau = 6.28318530718;
    bool yes = true;
    const char ca[] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
        0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
    };
    return 0;
}

with

g++ a.cpp

one gets an a.out binary. Using strings, it's possible to read the literal strings from the program, i.e.,

strings a.out | grep xyz
abcdefghijklmnopqrstuvwxyz

Is it also possible to get the other literals? How?


Solution

  • Compiling

    int main(void)
    {
        int a = 1234567890;
        return 0;
    }
    

    with g++ a.cpp and inspecting the output with

    objdump -d a.out
    

    gives

    [...]
    0000000000001119 <main>:
        1119:   55                      push   %rbp
        111a:   48 89 e5                mov    %rsp,%rbp
        111d:   c7 45 fc d2 02 96 49    movl   $0x499602d2,-0x4(%rbp)
        1124:   b8 00 00 00 00          mov    $0x0,%eax
        1129:   5d                      pop    %rbp
        112a:   c3                      ret
    [...]
    

    0x499602d2 is the hex-representation of 1234567890, so there's that.

    The same with

    int main(void)
    {
        const char ca[] = {
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
            0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
            0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
        };
        return 0;
    }
    

    gives

    0000000000001139 <main>:
        1139:   55                      push   %rbp
        113a:   48 89 e5                mov    %rsp,%rbp
        113d:   48 83 ec 30             sub    $0x30,%rsp
        1141:   64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
        1148:   00 00 
        114a:   48 89 45 f8             mov    %rax,-0x8(%rbp)
        114e:   31 c0                   xor    %eax,%eax
        1150:   48 b8 00 01 02 03 04    movabs $0x706050403020100,%rax
        1157:   05 06 07 
        115a:   48 ba 08 09 0a 0b 0c    movabs $0xf0e0d0c0b0a0908,%rdx
        1161:   0d 0e 0f 
        1164:   48 89 45 d0             mov    %rax,-0x30(%rbp)
        1168:   48 89 55 d8             mov    %rdx,-0x28(%rbp)
        116c:   48 b8 10 11 12 13 14    movabs $0x1716151413121110,%rax
        1173:   15 16 17 
        1176:   48 ba 18 19 1a 1b 1c    movabs $0x1f1e1d1c1b1a1918,%rdx
        117d:   1d 1e 1f 
        1180:   48 89 45 e0             mov    %rax,-0x20(%rbp)
        1184:   48 89 55 e8             mov    %rdx,-0x18(%rbp)
        1188:   b8 00 00 00 00          mov    $0x0,%eax
        118d:   48 8b 55 f8             mov    -0x8(%rbp),%rdx
        1191:   64 48 2b 14 25 28 00    sub    %fs:0x28,%rdx
        1198:   00 00 
        119a:   74 05                   je     11a1 <main+0x68>
        119c:   e8 8f fe ff ff          call   1030 <__stack_chk_fail@plt>
        11a1:   c9                      leave
        11a2:   c3                      ret
    

    The char array is present in the four blocks 1150, 115a, 116c, and 1176.