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...