1

I am trying to confuse objdump to solve the first exercise of chapter 6 in Practical Binary Analysis. Admittedly I am super weak with inline assembler but I made a best-effort attempt and tried to get it to do so. I was unable to directly embed inline data into the function (probably because I am missing something) without causing a segmentation fault when run. Obviously, the program should run correctly but screw up the linear disassembler.

For example, if I just dump data bytes directly into the function gcc will not interpret it correctly and cause it to segfault due to a bad assembly:

#include <stdio.h>

int main(int argc, char **argv)
{
    asm(".intel_syntax noprefix");
    asm(".ascii \"\\x6a\\x20\\x89\\x7d\\xec\\xc7\" \n");

    int x = 1;
    printf("%d\n", x);
}

This obvious screws up objdump...

0000000000001149 <main>:
    1149:   f3 0f 1e fa             endbr64 
    114d:   55                      push   rbp
    114e:   48 89 e5                mov    rbp,rsp
    1151:   48 83 ec 20             sub    rsp,0x20
    1155:   89 7d ec                mov    DWORD PTR [rbp-0x14],edi
    1158:   48 89 75 e0             mov    QWORD PTR [rbp-0x20],rsi
    115c:   6a 20                   push   0x20
    115e:   89 7d ec                mov    DWORD PTR [rbp-0x14],edi
    1161:   c7 c7 45 fc 01 00       mov    edi,0x1fc45
    1167:   00 00                   add    BYTE PTR [rax],al
    1169:   8b 45 fc                mov    eax,DWORD PTR [rbp-0x4]
    116c:   89 c6                   mov    esi,eax
    116e:   48 8d 3d 8f 0e 00 00    lea    rdi,[rip+0xe8f]        # 2004 <_IO_stdin_used+0x4>
    1175:   b8 00 00 00 00          mov    eax,0x0
    117a:   e8 d1 fe ff ff          call   1050 <printf@plt>
    117f:   b8 00 00 00 00          mov    eax,0x0
    1184:   c9                      leave  
    1185:   c3                      ret    
    1186:   66 2e 0f 1f 84 00 00    nop    WORD PTR cs:[rax+rax*1+0x0]
    118d:   00 00 00 

There are nonsense bytes starting at 155c. But this will seg fault naturally because its clobbering all sorts of stuff.

If I try something more tame it doesn't segfault but it also doesn't force desync:

#include <stdio.h>

__asm__(".intel_syntax noprefix\n"
        "array: .word 0x20, 0x20, 0x20, 0x20\n");

int main(int argc, char **argv)
{
    int x = 1;
    printf("%d\n", x);
}

This will run but as expected array will live in it's own section:

0000000000001149 <array>:
    1149:   20 00                   and    BYTE PTR [rax],al
    114b:   20 00                   and    BYTE PTR [rax],al
    114d:   20 00                   and    BYTE PTR [rax],al
    114f:   20 00                   and    BYTE PTR [rax],al

and while objdump translates this as code it is coincidence and isn't desync'd.

What am I missing to force this? I have been reading assembly directives and documentation for the better part of a day now and don't seem to be arriving at any better conclusions.

EDIT:

I have been able to get it to read data as code using the following:

#include <stdio.h>

int main(int argc, char **argv)
{
    asm volatile goto ("jmp %l[result]\n"
        :
        :
        :
        : result);
    asm volatile(".ascii \"\\x6a\\x20\\x89\\x7d\\xEC\\x38\\x67\\x20\" \n");

    int x = 1;
    result:
        printf("%d\n", x);
}
0000000000001149 <main>:
    1149:   f3 0f 1e fa             endbr64 
    114d:   55                      push   rbp
    114e:   48 89 e5                mov    rbp,rsp
    1151:   48 83 ec 20             sub    rsp,0x20
    1155:   89 7d ec                mov    DWORD PTR [rbp-0x14],edi
    1158:   48 89 75 e0             mov    QWORD PTR [rbp-0x20],rsi
    115c:   eb 0f                   jmp    116d <main+0x24>
    115e:   6a 20                   push   0x20
    1160:   89 7d ec                mov    DWORD PTR [rbp-0x14],edi
    1163:   38 67 20                cmp    BYTE PTR [rdi+0x20],ah
    1166:   c7 45 fc 01 00 00 00    mov    DWORD PTR [rbp-0x4],0x1
    116d:   8b 45 fc                mov    eax,DWORD PTR [rbp-0x4]
    1170:   89 c6                   mov    esi,eax
    1172:   48 8d 3d 8b 0e 00 00    lea    rdi,[rip+0xe8b]        # 2004 <_IO_stdin_used+0x4>
    1179:   b8 00 00 00 00          mov    eax,0x0
    117e:   e8 cd fe ff ff          call   1050 <printf@plt>
    1183:   b8 00 00 00 00          mov    eax,0x0
    1188:   c9                      leave  
    1189:   c3                      ret    
    118a:   66 0f 1f 44 00 00       nop    WORD PTR [rax+rax*1+0x0]

But this feels like cheating to me because to any even novice reverse engineer the unconditional jump is completely obvious. Though now the code works and there's garbage data bytes being read as code...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.