gcc -fno-stack-protector for linking not work - gcc

My gcc version : gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
the following is my makefile
all : main.o utility.o
gcc -fno-stack-protector -Wl,-z,execstack -o binary main.o utility.o -lcrypto
main : main.c
gcc -z execstack -fno-stack-protector main.c -c
utility: utility.c
gcc -z execstack -fno-stack-protector utility.c -c
The file utility.o and main.o does not have stack guard
But after linking there are some stack guard
objdump -D binary | grep chk
080488d0 <__stack_chk_fail#plt>:
8048e30: e8 9b fa ff ff call 80488d0 <__stack_chk_fail#plt>
80494dd: e8 ee f3 ff ff call 80488d0 <__stack_chk_fail#plt>
80498e2: e8 e9 ef ff ff call 80488d0 <__stack_chk_fail#plt>
8049b92: e8 39 ed ff ff call 80488d0 <__stack_chk_fail#plt>
8049c9e: e8 2d ec ff ff call 80488d0 <__stack_chk_fail#plt>
8049da2: e8 29 eb ff ff call 80488d0 <__stack_chk_fail#plt>
804a137: e8 94 e7 ff ff call 80488d0 <__stack_chk_fail#plt>
How to disable it?

the following is my makefile
gcc -z execstack -fno-stack-protector main.c -c
That command is bogus; if anything it should have -Wl,-z,execstack. However, since that's a linker option, and you are not linking here, best to remove -z exestack completely.
But after linking there are some stack guard
The calls to __stack_chk_fail must be coming from some code linked into your binary. Perhaps from libcrypto.a, or from libgcc.a. You can see where they are coming from, in two ways:
gcc -fno-stack-protector -Wl,-z,execstack -o binary main.o utility.o \
-lcrypto -Wl,-y,__stack_chk_fail
will produce messages like this:
/some/libfoo.a(bar.o): reference to __stack_chk_fail # you care about this one!
/usr/lib/libc.so.6: definition of __stack_chk_fail
Or you can use the binary you already built:
objdump -d binary | egrep '>:$|__stack_chk_fail' | grep -B1 __stack_chk_fail
That should tell you which functions inside the binary reference __stack_chk_fail, and from that you should be able to guess where these functions are coming from.
P.S. Unless you are studying buffer overflow exploitation techniques, disabling stack protector and linking with -z,execstack is a really bad idea.

Related

Does GCC generate wrong assembly code for the "jal" instruction of riscv?

generate jal instruction for riscv gets the unexpected code
I have a riscv assembly code in test_jal.s:
jal a0, 42
And I compile it with
riscv64-linux-gnu-gcc -c -Wl,-Ttext=0x0 -nostdlib -mno-relax -o test_jal test_jal.s
Then I generate the raw riscv binary by
riscv64-linux-gnu-objcopy -O binary test_jal test_jal.bin
I use hexdump -C test_jal.bin to generate its hex code:
6F 05 00 00
Then I use riscv64-linux-gnu-objdump to disasm it. I got
jal a0,0x0
May I do something wrong?
System: WSL ubuntu 22.04 gcc verison: 9.3.0

Is there any reference to "main" in the default linker scripts of arm-none-eabi that could interfere when linking from the command line

When using the gnu toolchain particularly arm-none-eabi is there any reason why when using the command line linker option it resorts to what seems an incorrect address to the start of 'main'. However, when 'main' is anything else the correct starting address and stack is initialized. For example,
.thumb
.syntax unified
.globl _start
_start:
.word 0x20001000
.word reset
reset:
bl main
b .
int main ( void )
{
return(0);
}
arm-none-eabi-gcc -O2 -c -mthumb main.c -o main.o
arm-none-eabi-as start.s -o start.o
arm-none-eabi-gcc -O2 -c -mthumb main.c -o main.o
arm-none-eabi-ld -Ttext=0x08000000 start.o main.o -o main.elf
arm-none-eabi-objdump -d main.elf
main.elf: file format elf32-littlearm
Disassembly of section .text:
08000000 <main>:
8000000: 2000 movs r0, #0
8000002: 4770 bx lr
08000004 <_start>:
8000004: 20001000 .word 0x20001000
8000008: 0800000c .word 0x0800000c
0800000c <reset>:
800000c: f7ff fff8 bl 8000000 <main>
8000010: e7fe b.n 8000010 <reset+0x4>
in the disassembly the output above doesn't initialize the stack 0x20001000 and start of rom 0x08000000 correctly from what I notice, but..
.thumb
.syntax unified
.globl _start
_start:
.word 0x20001000
.word reset
reset:
bl notmain
b .
int notmain ( void )
{
return(0);
}
arm-none-eabi-gcc -O2 -c -mthumb main.c -o main.o
arm-none-eabi-as start.s -o start.o
arm-none-eabi-gcc -O2 -c -mthumb main.c -o main.o
arm-none-eabi-ld -Ttext=0x08000000 start.o main.o -o main.elf
arm-none-eabi-objdump -d main.elf
main.elf: file format elf32-littlearm
Disassembly of section .text:
08000000 <_start>:
8000000: 20001000 .word 0x20001000
8000004: 08000008 .word 0x08000008
08000008 <reset>:
8000008: f000 f802 bl 8000010 <xmain>
800000c: e7fe b.n 800000c <reset+0x4>
...
08000010 <notmain>:
8000010: 2000 movs r0, #0
8000012: 4770 bx lr
I tried looking through the toolchain in my files to find any other reference to main pertaining to linker scripts and got some other help along the way, but there doesnt seem to be a clear solution as to why this is. Of course, if you create your own linker or a generated one you wont run into this problem, but I was just curious as I am trying to learn the tool a bit more.
..but I was just curious as I am trying to learn the tool a bit more
The arm-eabi-none is meant to be used with newlib (as a guess because you have not stated otherwise). This can process elf format files and it is a 'library', but there is no OS. If newlib mechanics want main() to be first, the tool will set things up like this. You don't want an elf file, but a binary. If you want a binary (ihex, srec, etc), then use a linker script! This is what it is meant for.
Use ld --verbose to see the default linker script. You are complaining about the order of emitted .text, but you have done nothing to define the ordering. The linker script may need main to be first so that some other library feature may work. You have a reset vector and a CPU which initializes the stack and 'reset vector' or initial code.
This is still emitted in the 'bad case', but it is not placed correctly. You need to have a custom linker script and position this a the first thing in the binary. Relying on the linker to place it correctly is error prone. An upgrade of tools can definitely change the order.
See: Can _start be a thumb function, were you have options like, -nostartfiles -static -nostdlib and use a custom linker script as an elf binary is unlikely to be understood and you need to flash/burn a binary to whatever boot device (or CPU built-in) is going to read the reset vectors.

gcc assembler - create only the minimal instructions necessary

I have created a very minimal application in assembly. It sets some registers to 0 and does a multiplication. Nothing fancy.
However, the gcc adds a lot of stuff to the machine code I do not want.
A small list of the stuff I find in the objdump:
deregister_tm_clones
register_tm_clones
__do_global_dtors_aux
frame_dummy
__libc_fini_array
memset
and a few more
I know that I do not need them, but I have no idea how I can tell to compiler to stop including them. I tried to use optimization options, but this did not change anything.
I compile it basically like: GCC -o ./main.elf ./main.S
Thank you very much for any help!
GCC automatically links the C / C++ runtime start-up crt0.o and the standard library. You can provide your own startup code to override the default and provide command line options to force it not to link no the standard library.
Options controlling startup and default libraries include:
-nostartfiles
-nostdlib
-nodefaultlubs
-nolibc
Each affects the link in a different way, but in this case -nostdlib will exclude both crt0.o and standard libraries. Of course if your code makes no reference to the standard library then nothing will be linked in any case, but explicitly excluding it will helpfully generate a link error if something does reference it.
See: https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html
Be aware that if your code does not establish a valid C runtime environment, providing for example static initialisation and a stack (a minimum), then some C code may not run in the manner intended. You may also need to specify the entry point via --entry=entry if you do not use the same default entry point as crt0 (_start I think).
Alternatively you can invoke gcc with the -c option and separately invoke the linker ld without specifying any library.
so.S:
nop
nop
then build.
as so.S -o so.o
ld -Ttext=0x1000 so.o -o so.elf
objdump -D so.elf
Disassembly of section .text:
0000000000001000 <__bss_start-0x200002>:
1000: 90 nop
1001: 90 nop
objcopy -O binary so.elf so.bin
hexdump -C so.bin
00000000 90 90 |..|
00000002
using gcc
gcc -nostartfiles -nostdlib -nodefaultlibs -ffreestanding so.S -Xlinker "-Ttext=0x1000" -o so.elf
this leaves extra garbage in the file, but
gcc so.S -c -o so.o
ld -Ttext=0x2000 so.o -o so.elf
ld: warning: cannot find entry symbol _start; defaulting to 0000000000002000
objdump -D so.elf
Disassembly of section .text:
0000000000002000 <__bss_start-0x200002>:
2000: 90 nop
2001: 90 nop
But if writing assembly language you might as well use the assembler not the compiler.
_start is not required unless you need an entry point defined in the file then you need to do this:
.globl _start
_start:
plus possibly something in the linker to call that out as the entry point for file formats like elf, exe, etc.
works for cross compiling as well
arm-none-eabi-as so.s -o so.o
arm-none-eabi-ld -Ttext=0x3000 so.o -o so.elf
arm-none-eabi-ld: warning: cannot find entry symbol _start; defaulting to 0000000000003000
arm-none-eabi-objdump -D so.elf
so.elf: file format elf32-littlearm
Disassembly of section .text:
00003000 <__bss_end__-0x10008>:
3000: e1a00000 nop ; (mov r0, r0)
3004: e1a00000 nop ; (mov r0, r0)
pdp11-aout-as so.s -o so.elf
pdp11-aout-as so.s -o so.o
pdp11-aout-ld -Ttext=0x400 so.o -o so.elf
pdp11-aout-objdump -D so.elf
so.elf: file format a.out-pdp11
Disassembly of section .text:
00000400 <so.o>:
400: 00a0 nop
402: 00a0 nop
and so on.

clang appears to use gcc

When I compile a simple hello world program using clang, in the comments of the elf64 file I still find information related to GCC. Why? I'm using clang not gcc.
I'm using ubuntu 16.04.
username#ubuntu:~$ clang++ -stdlib=libc++ test.cpp
username#ubuntu:~$ objdump --full-contents --section=.comment a.out
a.out: file format elf64-x86-64
Contents of section .comment:
0000 4743433a 20285562 756e7475 20352e34 GCC: (Ubuntu 5.4
0010 2e302d36 7562756e 7475317e 31362e30 .0-6ubuntu1~16.0
0020 342e3429 20352e34 2e302032 30313630 4.4) 5.4.0 20160
0030 36303900 636c616e 67207665 7273696f 609.clang versio
0040 6e20342e 302e3020 28746167 732f5245 n 4.0.0 (tags/RE
0050 4c454153 455f3430 302f6669 6e616c29 LEASE_400/final)
0060 00 .
username#ubuntu:~$
test.cpp is:
#include <iostream>
int main(int argc, char* argv[])
{
std::cout << argc << std::endl;
return 0;
}
I also ran
username#ubuntu:~$ sudo update-alternatives --config c++
[sudo] password for username:
There are 2 choices for the alternative c++ (providing /usr/bin/c++).
Selection Path Priority Status
------------------------------------------------------------
0 /usr/bin/g++ 20 auto mode
* 1 /usr/bin/clang++-libc++ 5 manual mode
2 /usr/bin/g++ 20 manual mode
Press <enter> to keep the current choice[*], or type selection number:
username#ubuntu:~$
Is this ok? why?
It's because you're linking with a C runtime (from Glibc) built with GCC, and the linker is merging the two together.
$ clang++ -c --stdlib=libc++ test.cpp
$ objdump --full-contents --section=.comment test.o
test.o: file format elf64-x86-64
Contents of section .comment:
0000 00636c61 6e672076 65727369 6f6e2034 .clang version 4
0010 2e302e30 20287461 67732f52 454c4541 .0.0 (tags/RELEA
0020 53455f34 30302f66 696e616c 2900 SE_400/final).
$ clang++ --verbose test.o
"/usr/bin/ld" --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib64/crt1.o /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib64/crti.o /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/crtbegin.o -L/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1 -L/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib64 -L/usr/bin/../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../.. -L/usr/bin/../lib -L/lib -L/usr/lib test.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/crtend.o /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib64/crtn.o
$ objdump --full-contents --section=.comment /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib64/crt1.o
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib64/crt1.o: file format elf64-x86-64
Contents of section .comment:
0000 00474343 3a202847 4e552920 362e332e .GCC: (GNU) 6.3.
0010 31203230 31373033 303600 1 20170306.
$ objdump --full-contents --section=.comment a.out
a.out: file format elf64-x86-64
Contents of section .comment:
0000 4743433a 2028474e 55292036 2e332e31 GCC: (GNU) 6.3.1
0010 20323031 37303330 3600636c 616e6720 20170306.clang
0020 76657273 696f6e20 342e302e 30202874 version 4.0.0 (t
0030 6167732f 52454c45 4153455f 3430302f ags/RELEASE_400/
0040 66696e61 6c2900 final).
My system has slightly different versions from yours, but you can see that the Clang-compiled object only has the Clang identifier in it, the C runtime object has the GCC identifier in it, and the final binary has both.

How to specify entry address for a macho file

I have an asm file test.S:
.text
.globl start
start:
movw %cs, %ax
movw %ax, %ds
Then I execute
clang -m32 -fno-builtin -Wall -ggdb -nostdinc -fno-stack-protector -O0 -nostdinc -c test.S -o test.o
ld test.o -o test.bin
gobjdump -S test.bin
I get
test.bin: file format mach-o-i386
Disassembly of section .text:
00001ffa <start>:
1ffa: 66 8c c8 mov %cs,%ax
1ffd: 66 8e d8 mov %ax,%ds
Notice that the address of start is 0x00001ffa, my question is how can I specify this address? I tried to use ld -segaddr, but it doesn't work. My OS is OS X 10.11

Resources