Incorrect NASM indirect addressing assembly on macOS - macos

Assembling the following code on macOS:
global start
default rel
section .text
start:
lea rdx, [buffer + 0]
lea rdx, [buffer + 1]
lea rdx, [buffer + 2]
lea rdx, [buffer + 3]
lea rdx, [buffer + 4]
lea rdx, [buffer + 5]
lea rdx, [buffer + 6]
lea rdx, [buffer + 7]
lea rdx, [buffer + 8]
section .data
buffer: db 0,0,0
using the command nasm -fmacho64 -w+all test.asm -o test.o, yields: (with gobjdump -d test.o)
0000000000000000 <start>:
0: 48 8d 15 38 00 00 00 lea 0x38(%rip),%rdx # 3f <buffer>
7: 48 8d 15 32 00 00 00 lea 0x32(%rip),%rdx # 40 <buffer+0x1>
e: 48 8d 15 2c 00 00 00 lea 0x2c(%rip),%rdx # 41 <buffer+0x2>
15: 48 8d 15 26 00 00 00 lea 0x26(%rip),%rdx # 42 <buffer+0x3>
1c: 48 8d 15 20 00 00 00 lea 0x20(%rip),%rdx # 43 <buffer+0x4>
23: 48 8d 15 1a 00 00 00 lea 0x1a(%rip),%rdx # 44 <buffer+0x5>
2a: 48 8d 15 14 00 00 00 lea 0x14(%rip),%rdx # 45 <buffer+0x6>
31: 48 8d 15 0e 00 00 00 lea 0xe(%rip),%rdx # 46 <buffer+0x7>
38: 48 8d 15 08 00 00 00 lea 0x8(%rip),%rdx # 47 <buffer+0x8>
This looks correct. When then linking that into an executable using ld test.o -o test, we get: (with gobjdump -d test)
0000000000001fc1 <start>:
1fc1: 48 8d 15 38 00 00 00 lea 0x38(%rip),%rdx # 2000 <buffer>
1fc8: 48 8d 15 32 00 00 00 lea 0x32(%rip),%rdx # 2001 <buffer+0x1>
1fcf: 48 8d 15 2c 00 00 00 lea 0x2c(%rip),%rdx # 2002 <buffer+0x2>
1fd6: 48 8d 15 23 00 00 00 lea 0x23(%rip),%rdx # 2000 <buffer>
1fdd: 48 8d 15 1d 00 00 00 lea 0x1d(%rip),%rdx # 2001 <buffer+0x1>
1fe4: 48 8d 15 17 00 00 00 lea 0x17(%rip),%rdx # 2002 <buffer+0x2>
1feb: 48 8d 15 11 00 00 00 lea 0x11(%rip),%rdx # 2003 <buffer+0x3>
1ff2: 48 8d 15 0b 00 00 00 lea 0xb(%rip),%rdx # 2004 <buffer+0x4>
1ff9: 48 8d 15 05 00 00 00 lea 0x5(%rip),%rdx # 2005 <buffer+0x5>
And suddenly, unexpectedly, buffer + n gets changed into buffer + (n - 3) if n >= 3. The nasm version I'm using is 2.13.01 and the ld is macOS Sierra's system linker, with ld -v giving:
#(#)PROGRAM:ld PROJECT:ld64-274.2
configured to support archs: armv6 armv7 armv7s arm64 i386 x86_64 x86_64h armv6m armv7k armv7m armv7em (tvOS)
LTO support using: LLVM version 8.0.0, (clang-800.0.42.1)
TAPI support using: Apple TAPI version 1.30
Why is this happening? Note that the same code seems to assemble and link fine on linux, as well as using yasm. In other places I read that nasm has some weird problems with the Mach-O 64 format, so this is probably a nasm bug in that area.

This seems to be fixed in nasm version 2.13.03, as tested today. (Also in 2.13.02, but that version has other problems with the macho64 target anyway, re #MichaelPetch; .02's output is equal in this case to .03's.) The output is as follows for the test.asm and commands given in the question.
nasm -fmacho64 -w+all test.asm -o test.o; gobjdump -d test.o:
test.o: file format mach-o-x86-64
Disassembly of section .text:
0000000000000000 <start>:
0: 48 8d 15 00 00 00 00 lea 0x0(%rip),%rdx # 7 <start+0x7>
7: 48 8d 15 01 00 00 00 lea 0x1(%rip),%rdx # f <start+0xf>
e: 48 8d 15 02 00 00 00 lea 0x2(%rip),%rdx # 17 <start+0x17>
15: 48 8d 15 03 00 00 00 lea 0x3(%rip),%rdx # 1f <start+0x1f>
1c: 48 8d 15 04 00 00 00 lea 0x4(%rip),%rdx # 27 <start+0x27>
23: 48 8d 15 05 00 00 00 lea 0x5(%rip),%rdx # 2f <start+0x2f>
2a: 48 8d 15 06 00 00 00 lea 0x6(%rip),%rdx # 37 <start+0x37>
31: 48 8d 15 07 00 00 00 lea 0x7(%rip),%rdx # 3f <buffer>
38: 48 8d 15 08 00 00 00 lea 0x8(%rip),%rdx # 47 <buffer+0x8>
ld test.o -o test; gobjdump -d test:
test: file format mach-o-x86-64
Disassembly of section .text:
0000000000001fc1 <start>:
1fc1: 48 8d 15 38 00 00 00 lea 0x38(%rip),%rdx # 2000 <buffer>
1fc8: 48 8d 15 32 00 00 00 lea 0x32(%rip),%rdx # 2001 <buffer+0x1>
1fcf: 48 8d 15 2c 00 00 00 lea 0x2c(%rip),%rdx # 2002 <buffer+0x2>
1fd6: 48 8d 15 26 00 00 00 lea 0x26(%rip),%rdx # 2003 <buffer+0x3>
1fdd: 48 8d 15 20 00 00 00 lea 0x20(%rip),%rdx # 2004 <buffer+0x4>
1fe4: 48 8d 15 1a 00 00 00 lea 0x1a(%rip),%rdx # 2005 <buffer+0x5>
1feb: 48 8d 15 14 00 00 00 lea 0x14(%rip),%rdx # 2006 <buffer+0x6>
1ff2: 48 8d 15 0e 00 00 00 lea 0xe(%rip),%rdx # 2007 <buffer+0x7>
1ff9: 48 8d 15 08 00 00 00 lea 0x8(%rip),%rdx # 2008 <buffer+0x8>
Worth noting is that my ld has updated and ld -v now gives:
#(#)PROGRAM:ld PROJECT:ld64-305
configured to support archs: armv6 armv7 armv7s arm64 i386 x86_64 x86_64h armv6m armv7k armv7m armv7em (tvOS)
LTO support using: LLVM version 9.0.0, (clang-900.0.39.2) (static support for 21, runtime is 21)
TAPI support using: Apple TAPI version 900.0.15 (tapi-900.0.15)

Related

Locate jump tables in x86 assembly

Where are jump tables located in x86 elf code?
progname: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 ec 10 sub $0x10,%rsp
8: c7 45 fc 02 00 00 00 movl $0x2,-0x4(%rbp)
f: 83 7d fc 09 cmpl $0x9,-0x4(%rbp)
13: 0f 87 ac 00 00 00 ja c5 <main+0xc5>
19: 8b 45 fc mov -0x4(%rbp),%eax
1c: 48 8b 04 c5 00 00 00 mov 0x0(,%rax,8),%rax
23: 00
20: R_X86_64_32S .rodata+0x48
24: ff e0 jmpq *%rax
26: bf 00 00 00 00 mov $0x0,%edi
27: R_X86_64_32 .rodata
2b: b8 00 00 00 00 mov $0x0,%eax
30: e8 00 00 00 00 callq 35 <main+0x35>
31: R_X86_64_PLT32 printf-0x4
35: e9 9b 00 00 00 jmpq d5 <main+0xd5>
3a: bf 00 00 00 00 mov $0x0,%edi
3b: R_X86_64_32 .rodata+0xc
3f: b8 00 00 00 00 mov $0x0,%eax
44: e8 00 00 00 00 callq 49 <main+0x49>
45: R_X86_64_PLT32 printf-0x4
49: e9 87 00 00 00 jmpq d5 <main+0xd5>
4e: bf 00 00 00 00 mov $0x0,%edi
4f: R_X86_64_32 .rodata+0x18
53: b8 00 00 00 00 mov $0x0,%eax
58: e8 00 00 00 00 callq 5d <main+0x5d>
59: R_X86_64_PLT32 printf-0x4
5d: eb 76 jmp d5 <main+0xd5>
5f: bf 00 00 00 00 mov $0x0,%edi
60: R_X86_64_32 .rodata
64: b8 00 00 00 00 mov $0x0,%eax
69: e8 00 00 00 00 callq 6e <main+0x6e>
6a: R_X86_64_PLT32 printf-0x4
6e: eb 65 jmp d5 <main+0xd5>
70: bf 00 00 00 00 mov $0x0,%edi
71: R_X86_64_32 .rodata+0xc
75: b8 00 00 00 00 mov $0x0,%eax
7a: e8 00 00 00 00 callq 7f <main+0x7f>
7b: R_X86_64_PLT32 printf-0x4
7f: eb 54 jmp d5 <main+0xd5>
81: bf 00 00 00 00 mov $0x0,%edi
82: R_X86_64_32 .rodata+0x18
86: b8 00 00 00 00 mov $0x0,%eax
8b: e8 00 00 00 00 callq 90 <main+0x90>
8c: R_X86_64_PLT32 printf-0x4
90: eb 43 jmp d5 <main+0xd5>
92: bf 00 00 00 00 mov $0x0,%edi
93: R_X86_64_32 .rodata
97: b8 00 00 00 00 mov $0x0,%eax
9c: e8 00 00 00 00 callq a1 <main+0xa1>
9d: R_X86_64_PLT32 printf-0x4
a1: eb 32 jmp d5 <main+0xd5>
a3: bf 00 00 00 00 mov $0x0,%edi
a4: R_X86_64_32 .rodata+0xc
a8: b8 00 00 00 00 mov $0x0,%eax
ad: e8 00 00 00 00 callq b2 <main+0xb2>
ae: R_X86_64_PLT32 printf-0x4
b2: eb 21 jmp d5 <main+0xd5>
b4: bf 00 00 00 00 mov $0x0,%edi
b5: R_X86_64_32 .rodata+0x18
b9: b8 00 00 00 00 mov $0x0,%eax
be: e8 00 00 00 00 callq c3 <main+0xc3>
bf: R_X86_64_PLT32 printf-0x4
c3: eb 10 jmp d5 <main+0xd5>
c5: bf 00 00 00 00 mov $0x0,%edi
c6: R_X86_64_32 .rodata+0x24
ca: b8 00 00 00 00 mov $0x0,%eax
cf: e8 00 00 00 00 callq d4 <main+0xd4>
d0: R_X86_64_PLT32 printf-0x4
d4: 90 nop
d5: b8 00 00 00 00 mov $0x0,%eax
da: c9 leaveq
db: c3 retq
I have a basic switch case with 10 cases (including default case). If x=2, then it goes to 2nd block in switch case code.
Need help in understanding where exactly gcc generated jump tables are located in elf files and in which section. I pasted output of objdump -dr progname above.

x86_64 assembly instructions changed in link stage of GCC

I'm compiling a program using the sqlite3 libary in Linux(centos7_64). As the user has an old CPU, I set the -march=nehalem flag in GCC (-march=nehalem -mtune=nehalem -m64 -O3). I find I can't limit the assembly instructions to nehalem, some BMI operations still exist in the final binary.
Follow the output step by step, I find the problem comes from the linker (ld).
libsqlite3.a:
632c2: 66 41 83 4f 26 01 orw $0x1,0x26(%r15)
632c8: 0f b6 84 24 80 00 00 movzbl 0x80(%rsp),%eax
632cf: 00
632d0: c1 e0 08 shl $0x8,%eax
632d3: 89 c2 mov %eax,%edx
632d5: 0f b6 84 24 81 00 00 movzbl 0x81(%rsp),%eax
632dc: 00
632dd: c1 e0 10 shl $0x10,%eax
632e0: 09 d0 or %edx,%eax
632e2: 8d 90 00 fe ff ff lea -0x200(%rax),%edx
632e8: 41 89 47 30 mov %eax,0x30(%r15)
632ec: 81 fa 00 fe 00 00 cmp $0xfe00,%edx
632f2: 0f 87 d1 05 00 00 ja 638c9 <sqlite3BtreeOpen+0xb29>
632f8: 8d 50 ff lea -0x1(%rax),%edx
632fb: 85 c2 test %eax,%edx
632fd: 0f 85 c6 05 00 00 jne 638c9 <sqlite3BtreeOpen+0xb29>
However, in the final binary:
9499f2: 66 41 83 4f 26 01 orw $0x1,0x26(%r15)
9499f8: 0f b6 84 24 80 00 00 movzbl 0x80(%rsp),%eax
9499ff: 00
949a00: 0f b6 94 24 81 00 00 movzbl 0x81(%rsp),%edx
949a07: 00
949a08: c1 e0 08 shl $0x8,%eax
949a0b: 89 c1 mov %eax,%ecx
949a0d: 89 d0 mov %edx,%eax
949a0f: c1 e0 10 shl $0x10,%eax
949a12: 09 c8 or %ecx,%eax
949a14: 8d 90 00 fe ff ff lea -0x200(%rax),%edx
949a1a: 41 89 47 30 mov %eax,0x30(%r15)
949a1e: 81 fa 00 fe 00 00 cmp $0xfe00,%edx
949a24: 0f 87 cf 05 00 00 ja 949ff9 <sqlite3BtreeOpen+0xb09>
949a2a: c4 e2 78 f3 c8 blsr %eax,%eax
949a2f: 85 c0 test %eax,%eax
949a31: 0f 85 c2 05 00 00 jne 949ff9 <sqlite3BtreeOpen+0xb09>
Notice the last few lines, the linker changed the lea to blsr, which is unexpected.
Thus, why will this happen. Will the linker (ld) optimize the code further? How to limit the instrutions for the linker to use?
Many thanks for the comments. I have found the problem, as Peter Cordes said in the comment, I linked to another set of sqlite library. I installed too many sets of GCC compiler environment, and each compiler has its own sqlite in its default library path. My project was managed by cmake, it remembered all previous GCC settings...
Steps to discover:
add -v flag to gcc commands.
copy the ld commands out, and add flag "--print-map -Map=demo.map", run the full ld command again.
search the library name (sqlite here) in demo.map, I clearly find another set of sqlite library has been linked. Realise how stupid I am...
Update: I have a new problem: if the library.a is compiled with an advanced CPU instruction, how to downgrade it in link stage, seems those instructions will be copied into binary without checking the -march flags in GCC.

gcc 5 does not detect stack smashing for inline functions but gcc 7 does

This is the code I used to test the stack protection feature of gcc.
static inline void charcpy(char* temp)
{
temp[0]='a';
temp[1]='b';
temp[2]='c';
temp[3]='d';
temp[4]='\0';
}
int main()
{
char temp[3];
charcpy(temp);
return 0;
}
When I compile with gcc 7.3 (without specifying any flags), I got the following runtime error on my desktop
*** stack smashing detected ***: <unknown> terminated
Aborted (core dumped)
The uname -a command gives the following for my desktop if it matters
Linux lixun-Desktop 4.15.0-36-generic #39-Ubuntu SMP Mon Sep 24 16:19:09 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
However, when I tried the same thing on a server machine using gcc 5.4, no error shows up. The uname -a command for the server machine is
Linux aggravation 4.4.0-137-generic #163-Ubuntu SMP Mon Sep 24 13:14:43 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
Then I use objdump -D a.out to check their assembly codes but still cannot figure out why the stack protection is not working on the server machine.
Here is the output on my desktop (I only paste the section I think might matter)
Disassembly of section .init:
0000000000000510 <_init>:
510: 48 83 ec 08 sub $0x8,%rsp
514: 48 8b 05 cd 0a 20 00 mov 0x200acd(%rip),%rax # 200fe8 <__gmon_start__>
51b: 48 85 c0 test %rax,%rax
51e: 74 02 je 522 <_init+0x12>
520: ff d0 callq *%rax
522: 48 83 c4 08 add $0x8,%rsp
526: c3 retq
Disassembly of section .plt:
0000000000000530 <.plt>:
530: ff 35 8a 0a 20 00 pushq 0x200a8a(%rip) # 200fc0 <_GLOBAL_OFFSET_TABLE_+0x8>
536: ff 25 8c 0a 20 00 jmpq *0x200a8c(%rip) # 200fc8 <_GLOBAL_OFFSET_TABLE_+0x10>
53c: 0f 1f 40 00 nopl 0x0(%rax)
0000000000000540 <__stack_chk_fail#plt>:
540: ff 25 8a 0a 20 00 jmpq *0x200a8a(%rip) # 200fd0 <__stack_chk_fail#GLIBC_2.4>
546: 68 00 00 00 00 pushq $0x0
54b: e9 e0 ff ff ff jmpq 530 <.plt>
Disassembly of section .plt.got:
0000000000000550 <__cxa_finalize#plt>:
550: ff 25 a2 0a 20 00 jmpq *0x200aa2(%rip) # 200ff8 <__cxa_finalize#GLIBC_2.2.5>
556: 66 90 xchg %ax,%ax
...
Disassembly of section .text:
0000000000000560 <_start>:
560: 31 ed xor %ebp,%ebp
562: 49 89 d1 mov %rdx,%r9
565: 5e pop %rsi
566: 48 89 e2 mov %rsp,%rdx
569: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
56d: 50 push %rax
56e: 54 push %rsp
56f: 4c 8d 05 ea 01 00 00 lea 0x1ea(%rip),%r8 # 760 <__libc_csu_fini>
576: 48 8d 0d 73 01 00 00 lea 0x173(%rip),%rcx # 6f0 <__libc_csu_init>
57d: 48 8d 3d 24 01 00 00 lea 0x124(%rip),%rdi # 6a8 <main>
584: ff 15 56 0a 20 00 callq *0x200a56(%rip) # 200fe0 <__libc_start_main#GLIBC_2.2.5>
58a: f4 hlt
58b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
...
000000000000066a <charcpy>:
66a: 55 push %rbp
66b: 48 89 e5 mov %rsp,%rbp
66e: 48 89 7d f8 mov %rdi,-0x8(%rbp)
672: 48 8b 45 f8 mov -0x8(%rbp),%rax
676: c6 00 61 movb $0x61,(%rax)
679: 48 8b 45 f8 mov -0x8(%rbp),%rax
67d: 48 83 c0 01 add $0x1,%rax
681: c6 00 62 movb $0x62,(%rax)
684: 48 8b 45 f8 mov -0x8(%rbp),%rax
688: 48 83 c0 02 add $0x2,%rax
68c: c6 00 63 movb $0x63,(%rax)
68f: 48 8b 45 f8 mov -0x8(%rbp),%rax
693: 48 83 c0 03 add $0x3,%rax
697: c6 00 64 movb $0x64,(%rax)
69a: 48 8b 45 f8 mov -0x8(%rbp),%rax
69e: 48 83 c0 04 add $0x4,%rax
6a2: c6 00 00 movb $0x0,(%rax)
6a5: 90 nop
6a6: 5d pop %rbp
6a7: c3 retq
00000000000006a8 <main>:
6a8: 55 push %rbp
6a9: 48 89 e5 mov %rsp,%rbp
6ac: 48 83 ec 10 sub $0x10,%rsp
6b0: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
6b7: 00 00
6b9: 48 89 45 f8 mov %rax,-0x8(%rbp)
6bd: 31 c0 xor %eax,%eax
6bf: 48 8d 45 f5 lea -0xb(%rbp),%rax
6c3: 48 89 c7 mov %rax,%rdi
6c6: e8 9f ff ff ff callq 66a <charcpy>
6cb: b8 00 00 00 00 mov $0x0,%eax
6d0: 48 8b 55 f8 mov -0x8(%rbp),%rdx
6d4: 64 48 33 14 25 28 00 xor %fs:0x28,%rdx
6db: 00 00
6dd: 74 05 je 6e4 <main+0x3c>
6df: e8 5c fe ff ff callq 540 <__stack_chk_fail#plt>
6e4: c9 leaveq
6e5: c3 retq
6e6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
6ed: 00 00 00
And this is the output on the server machine
Disassembly of section .init:
00000000004003f0 <_init>:
4003f0: 48 83 ec 08 sub $0x8,%rsp
4003f4: 48 8b 05 fd 0b 20 00 mov 0x200bfd(%rip),%rax # 600ff8 <_DYNAMIC+0x1d0>
4003fb: 48 85 c0 test %rax,%rax
4003fe: 74 05 je 400405 <_init+0x15>
400400: e8 3b 00 00 00 callq 400440 <__libc_start_main#plt+0x10>
400405: 48 83 c4 08 add $0x8,%rsp
400409: c3 retq
Disassembly of section .plt:
0000000000400410 <__stack_chk_fail#plt-0x10>:
400410: ff 35 f2 0b 20 00 pushq 0x200bf2(%rip) # 601008 <_GLOBAL_OFFSET_TABLE_+0x8>
400416: ff 25 f4 0b 20 00 jmpq *0x200bf4(%rip) # 601010 <_GLOBAL_OFFSET_TABLE_+0x10>
40041c: 0f 1f 40 00 nopl 0x0(%rax)
0000000000400420 <__stack_chk_fail#plt>:
400420: ff 25 f2 0b 20 00 jmpq *0x200bf2(%rip) # 601018 <_GLOBAL_OFFSET_TABLE_+0x18>
400426: 68 00 00 00 00 pushq $0x0
40042b: e9 e0 ff ff ff jmpq 400410 <_init+0x20>
0000000000400430 <__libc_start_main#plt>:
400430: ff 25 ea 0b 20 00 jmpq *0x200bea(%rip) # 601020 <_GLOBAL_OFFSET_TABLE_+0x20>
400436: 68 01 00 00 00 pushq $0x1
40043b: e9 d0 ff ff ff jmpq 400410 <_init+0x20>
Disassembly of section .plt.got:
0000000000400440 <.plt.got>:
400440: ff 25 b2 0b 20 00 jmpq *0x200bb2(%rip) # 600ff8 <_DYNAMIC+0x1d0>
400446: 66 90 xchg %ax,%ax
...
Disassembly of section .text:
0000000000400450 <_start>:
400450: 31 ed xor %ebp,%ebp
400452: 49 89 d1 mov %rdx,%r9
400455: 5e pop %rsi
400456: 48 89 e2 mov %rsp,%rdx
400459: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
40045d: 50 push %rax
40045e: 54 push %rsp
40045f: 49 c7 c0 40 06 40 00 mov $0x400640,%r8
400466: 48 c7 c1 d0 05 40 00 mov $0x4005d0,%rcx
40046d: 48 c7 c7 84 05 40 00 mov $0x400584,%rdi
400474: e8 b7 ff ff ff callq 400430 <__libc_start_main#plt>
400479: f4 hlt
40047a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
0000000000400546 <charcpy>:
400546: 55 push %rbp
400547: 48 89 e5 mov %rsp,%rbp
40054a: 48 89 7d f8 mov %rdi,-0x8(%rbp)
40054e: 48 8b 45 f8 mov -0x8(%rbp),%rax
400552: c6 00 61 movb $0x61,(%rax)
400555: 48 8b 45 f8 mov -0x8(%rbp),%rax
400559: 48 83 c0 01 add $0x1,%rax
40055d: c6 00 62 movb $0x62,(%rax)
400560: 48 8b 45 f8 mov -0x8(%rbp),%rax
400564: 48 83 c0 02 add $0x2,%rax
400568: c6 00 63 movb $0x63,(%rax)
40056b: 48 8b 45 f8 mov -0x8(%rbp),%rax
40056f: 48 83 c0 03 add $0x3,%rax
400573: c6 00 64 movb $0x64,(%rax)
400576: 48 8b 45 f8 mov -0x8(%rbp),%rax
40057a: 48 83 c0 04 add $0x4,%rax
40057e: c6 00 00 movb $0x0,(%rax)
400581: 90 nop
400582: 5d pop %rbp
400583: c3 retq
0000000000400584 <main>:
400584: 55 push %rbp
400585: 48 89 e5 mov %rsp,%rbp
400588: 48 83 ec 10 sub $0x10,%rsp
40058c: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
400593: 00 00
400595: 48 89 45 f8 mov %rax,-0x8(%rbp)
400599: 31 c0 xor %eax,%eax
40059b: 48 8d 45 f0 lea -0x10(%rbp),%rax
40059f: 48 89 c7 mov %rax,%rdi
4005a2: e8 9f ff ff ff callq 400546 <charcpy>
4005a7: b8 00 00 00 00 mov $0x0,%eax
4005ac: 48 8b 55 f8 mov -0x8(%rbp),%rdx
4005b0: 64 48 33 14 25 28 00 xor %fs:0x28,%rdx
4005b7: 00 00
4005b9: 74 05 je 4005c0 <main+0x3c>
4005bb: e8 60 fe ff ff callq 400420 <__stack_chk_fail#plt>
4005c0: c9 leaveq
4005c1: c3 retq
4005c2: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
4005c9: 00 00 00
4005cc: 0f 1f 40 00 nopl 0x0(%rax)
...
I also tried to specify -fstack-protector(-all or -strong) on the server machine, it still shows no error.
Anyone knows why there is the difference?
The server machine places the array temp into a different place in the main stack frame. It uses this operation to compute the address, with a 16-byte offset from the frame pointer:
40059b: 48 8d 45 f0 lea -0x10(%rbp),%rax
The other machine uses this instead:
6bf: 48 8d 45 f5 lea -0xb(%rbp),%rax
There is only an 11-byte offset from the frame pointer. The canary is stored at offset 8 in both cases.
As a result, on the server machine, there are 5 unused bytes after the array, and the overflow spills into that. The canary is not overwritten, which is why the overflow is not detected. But neither is the return address, so it is not possible to redirect execution here.
In real-world software, this would be a source-level stack-based buffer overflow which is not exploitable by accident in the compiled binary. Such things happen occasionally.

Disassemble exe file after compilation with gcc

This made One week i search for a solution, please help me.
This is my source code: myexe.c
#include <stdlib.h>
#include <stdio.h>
/* gcc -m32 -o myexe myexe.c */
int main(void)
{
system("ls /home/myexe");
return 0;
}
After complilation, I want to disassemble myexe and change ls /home/myexe to cat /home/myexe in the assembly code.
It is a exercice I received. Please help me!
myexe output:
ch11: format de fichier elf64-x86-64
Déassemblage de la section .init :
0000000000000530 <_init>:
530: 48 83 ec 08 sub $0x8,%rsp
534: 48 8b 05 a5 0a 20 00 mov 0x200aa5(%rip),%rax # 200fe0 <__gmon_start__>
53b: 48 85 c0 test %rax,%rax
53e: 74 02 je 542 <_init+0x12>
540: ff d0 callq *%rax
542: 48 83 c4 08 add $0x8,%rsp
546: c3 retq
Déassemblage de la section .plt :
0000000000000550 <.plt>:
550: ff 35 b2 0a 20 00 pushq 0x200ab2(%rip) # 201008 <_GLOBAL_OFFSET_TABLE_+0x8>
556: ff 25 b4 0a 20 00 jmpq *0x200ab4(%rip) # 201010 <_GLOBAL_OFFSET_TABLE_+0x10>
55c: 0f 1f 40 00 nopl 0x0(%rax)
0000000000000560 <system#plt>:
560: ff 25 b2 0a 20 00 jmpq *0x200ab2(%rip) # 201018 <system#GLIBC_2.2.5>
566: 68 00 00 00 00 pushq $0x0
56b: e9 e0 ff ff ff jmpq 550 <.plt>
Déassemblage de la section .plt.got :
0000000000000570 <.plt.got>:
570: ff 25 82 0a 20 00 jmpq *0x200a82(%rip) # 200ff8 <__cxa_finalize#GLIBC_2.2.5>
576: 66 90 xchg %ax,%ax
Déassemblage de la section .text :
0000000000000580 <_start>:
580: 31 ed xor %ebp,%ebp
582: 49 89 d1 mov %rdx,%r9
585: 5e pop %rsi
586: 48 89 e2 mov %rsp,%rdx
589: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
58d: 50 push %rax
58e: 54 push %rsp
58f: 4c 8d 05 aa 01 00 00 lea 0x1aa(%rip),%r8 # 740 <__libc_csu_fini>
596: 48 8d 0d 33 01 00 00 lea 0x133(%rip),%rcx # 6d0 <__libc_csu_init>
59d: 48 8d 3d 0c 01 00 00 lea 0x10c(%rip),%rdi # 6b0 <main>
5a4: ff 15 2e 0a 20 00 callq *0x200a2e(%rip) # 200fd8 <__libc_start_main#GLIBC_2.2.5>
5aa: f4 hlt
5ab: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
00000000000005b0 <deregister_tm_clones>:
5b0: 48 8d 3d 79 0a 20 00 lea 0x200a79(%rip),%rdi # 201030 <__TMC_END__>
5b7: 48 8d 05 79 0a 20 00 lea 0x200a79(%rip),%rax # 201037 <__TMC_END__+0x7>
5be: 55 push %rbp
5bf: 48 29 f8 sub %rdi,%rax
5c2: 48 89 e5 mov %rsp,%rbp
5c5: 48 83 f8 0e cmp $0xe,%rax
5c9: 76 15 jbe 5e0 <deregister_tm_clones+0x30>
5cb: 48 8b 05 fe 09 20 00 mov 0x2009fe(%rip),%rax # 200fd0 <_ITM_deregisterTMCloneTable>
5d2: 48 85 c0 test %rax,%rax
5d5: 74 09 je 5e0 <deregister_tm_clones+0x30>
5d7: 5d pop %rbp
5d8: ff e0 jmpq *%rax
5da: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
5e0: 5d pop %rbp
5e1: c3 retq
5e2: 0f 1f 40 00 nopl 0x0(%rax)
5e6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
5ed: 00 00 00
00000000000005f0 <register_tm_clones>:
5f0: 48 8d 3d 39 0a 20 00 lea 0x200a39(%rip),%rdi # 201030 <__TMC_END__>
5f7: 48 8d 35 32 0a 20 00 lea 0x200a32(%rip),%rsi # 201030 <__TMC_END__>
5fe: 55 push %rbp
5ff: 48 29 fe sub %rdi,%rsi
602: 48 89 e5 mov %rsp,%rbp
605: 48 c1 fe 03 sar $0x3,%rsi
609: 48 89 f0 mov %rsi,%rax
60c: 48 c1 e8 3f shr $0x3f,%rax
610: 48 01 c6 add %rax,%rsi
613: 48 d1 fe sar %rsi
616: 74 18 je 630 <register_tm_clones+0x40>
618: 48 8b 05 d1 09 20 00 mov 0x2009d1(%rip),%rax # 200ff0 <_ITM_registerTMCloneTable>
61f: 48 85 c0 test %rax,%rax
622: 74 0c je 630 <register_tm_clones+0x40>
624: 5d pop %rbp
625: ff e0 jmpq *%rax
627: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
62e: 00 00
630: 5d pop %rbp
631: c3 retq
632: 0f 1f 40 00 nopl 0x0(%rax)
636: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
63d: 00 00 00
0000000000000640 <__do_global_dtors_aux>:
640: 80 3d e9 09 20 00 00 cmpb $0x0,0x2009e9(%rip) # 201030 <__TMC_END__>
647: 75 27 jne 670 <__do_global_dtors_aux+0x30>
649: 48 83 3d a7 09 20 00 cmpq $0x0,0x2009a7(%rip) # 200ff8 <__cxa_finalize#GLIBC_2.2.5>
650: 00
651: 55 push %rbp
652: 48 89 e5 mov %rsp,%rbp
655: 74 0c je 663 <__do_global_dtors_aux+0x23>
657: 48 8b 3d ca 09 20 00 mov 0x2009ca(%rip),%rdi # 201028 <__dso_handle>
65e: e8 0d ff ff ff callq 570 <.plt.got>
663: e8 48 ff ff ff callq 5b0 <deregister_tm_clones>
668: 5d pop %rbp
669: c6 05 c0 09 20 00 01 movb $0x1,0x2009c0(%rip) # 201030 <__TMC_END__>
670: f3 c3 repz retq
672: 0f 1f 40 00 nopl 0x0(%rax)
676: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
67d: 00 00 00
0000000000000680 <frame_dummy>:
680: 48 8d 3d 61 07 20 00 lea 0x200761(%rip),%rdi # 200de8 <__JCR_END__>
687: 48 83 3f 00 cmpq $0x0,(%rdi)
68b: 75 0b jne 698 <frame_dummy+0x18>
68d: e9 5e ff ff ff jmpq 5f0 <register_tm_clones>
692: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
698: 48 8b 05 49 09 20 00 mov 0x200949(%rip),%rax # 200fe8 <_Jv_RegisterClasses>
69f: 48 85 c0 test %rax,%rax
6a2: 74 e9 je 68d <frame_dummy+0xd>
6a4: 55 push %rbp
6a5: 48 89 e5 mov %rsp,%rbp
6a8: ff d0 callq *%rax
6aa: 5d pop %rbp
6ab: e9 40 ff ff ff jmpq 5f0 <register_tm_clones>
00000000000006b0 <main>:
6b0: 55 push %rbp
6b1: 48 89 e5 mov %rsp,%rbp
6b4: 48 8d 3d 99 00 00 00 lea 0x99(%rip),%rdi # 754 <_IO_stdin_used+0x4>
6bb: e8 a0 fe ff ff callq 560 <system#plt>
6c0: b8 00 00 00 00 mov $0x0,%eax
6c5: 5d pop %rbp
6c6: c3 retq
6c7: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
6ce: 00 00
00000000000006d0 <__libc_csu_init>:
6d0: 41 57 push %r15
6d2: 41 56 push %r14
6d4: 41 89 ff mov %edi,%r15d
6d7: 41 55 push %r13
6d9: 41 54 push %r12
6db: 4c 8d 25 f6 06 20 00 lea 0x2006f6(%rip),%r12 # 200dd8 <__frame_dummy_init_array_entry>
6e2: 55 push %rbp
6e3: 48 8d 2d f6 06 20 00 lea 0x2006f6(%rip),%rbp # 200de0 <__init_array_end>
6ea: 53 push %rbx
6eb: 49 89 f6 mov %rsi,%r14
6ee: 49 89 d5 mov %rdx,%r13
6f1: 4c 29 e5 sub %r12,%rbp
6f4: 48 83 ec 08 sub $0x8,%rsp
6f8: 48 c1 fd 03 sar $0x3,%rbp
6fc: e8 2f fe ff ff callq 530 <_init>
701: 48 85 ed test %rbp,%rbp
704: 74 20 je 726 <__libc_csu_init+0x56>
706: 31 db xor %ebx,%ebx
708: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
70f: 00
710: 4c 89 ea mov %r13,%rdx
713: 4c 89 f6 mov %r14,%rsi
716: 44 89 ff mov %r15d,%edi
719: 41 ff 14 dc callq *(%r12,%rbx,8)
71d: 48 83 c3 01 add $0x1,%rbx
721: 48 39 dd cmp %rbx,%rbp
724: 75 ea jne 710 <__libc_csu_init+0x40>
726: 48 83 c4 08 add $0x8,%rsp
72a: 5b pop %rbx
72b: 5d pop %rbp
72c: 41 5c pop %r12
72e: 41 5d pop %r13
730: 41 5e pop %r14
732: 41 5f pop %r15
734: c3 retq
735: 90 nop
736: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
73d: 00 00 00
0000000000000740 <__libc_csu_fini>:
740: f3 c3 repz retq
Déassemblage de la section .fini :
0000000000000744 <_fini>:
744: 48 83 ec 08 sub $0x8,%rsp
748: 48 83 c4 08 add $0x8,%rsp
74c: c3 retq
If you want to disassemble your program you can use any of the large number of free and paid disassemblers that are out there.
If you simply want to change the command run by system, you do not need to disassemble the program. You can simply use a hex editor to modify the binary.

Compile code to raw binary

I'm trying to compile my code into raw binary and as suggested by other SO posts (like this and this) I tried objdump:
$ gcc -c foo.c
$ objcopy -O binary foo.o foo.bin
Then I tried to make sure if this is valid:
$ objdump -d foo.o
foo.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 ec 10 sub $0x10,%rsp
8: 89 7d fc mov %edi,-0x4(%rbp)
b: 48 89 75 f0 mov %rsi,-0x10(%rbp)
f: bf 00 00 00 00 mov $0x0,%edi
14: b8 00 00 00 00 mov $0x0,%eax
19: e8 00 00 00 00 callq 1e <main+0x1e>
1e: b8 00 00 00 00 mov $0x0,%eax
23: c9 leaveq
24: c3 ret
$ hexdump -C foo.bin
00000000 14 00 00 00 00 00 00 00 01 7a 52 00 01 78 10 01 |.........zR..x..|
00000010 1b 0c 07 08 90 01 00 00 1c 00 00 00 1c 00 00 00 |................|
00000020 00 00 00 00 25 00 00 00 00 41 0e 10 86 02 43 0d |....%....A....C.|
00000030 06 60 0c 07 08 00 00 00 |.`......|
00000038
Evidently something is wrong. I checked this with the results of a gcc cross-compilation, with much the same obviously incorrect results.
You can pass -j .text to objcopy.

Resources