segmentation error while injecting shellcode to stack smash - stack-overflow

I have been trying to understand how stack overflow attacks work. So far I can successfully redirect the return address to an instruction inside the original code. I have written a shellcode launcher in assembly and got it work inside a c program. With debugging using gdb, I obtained the hex representing the shellcode launcher and the c program works fine. Yet when I try to inject this hex string in another program I get the segmentation error.When I trace the return address I realized that it was successfully set to point the hex string before the program exits. snapshots show the steps. I am not able to figure out why the injection does not work given the fact that same code can create the shell in assembly and the return address of the main function was set to point the sc ( the string that creates new shell).
#include <stdio.h>
void main(){
asm(
"xorl %eax,%eax;"
"pushl %eax;"
"pushl $0x68732f2f;"
"pushl $0x6e69622f;"
"movl %esp,%ebx;"
"pushl %eax;"
"pushl %ebx;"
"movl %esp,%ecx;"
"movl %eax,%edx;"
"movb $0x0b,%al;"
"int $0x80;"
);
}
when I compile and run the above c code that includes assembly, it runs perfectly fine. I obtained the hex of the asm code in the c program above using gdb and generated following stack smash code.
char sc[]=
"\x31\xc0\x50\x68\x2f\x2f\x73"
"\x68\x68\x2f\x62\x69\x6e"
"\x89\xe3\x50\x53\x89\xe1"
"\x89\xc2\xb0\x0b\xcd\x80";
void main(){
int *ret;
ret=(int *)&ret+2;
(*ret)=(int)sc;
}
when I run the code I get the following error. Program received signal SIGSEGV, Segmentation fault. 0x0804a01c in sc ()

Solved it. problem is stack was not executable. Turns out you can make the stack executable with "gcc -z execstack"

Related

gcc compiler does not show segfault error

I am using mingw compiler on my windows 10 laptop. The following c code should display a segmentation fault error. But instead, it just does not show anything (empty output).
#include <stdio.h>
int main(){
main();
return 0;
}
I compile the code using:
gcc filename.c
But when I use some online c compilers, it shows segmentation fault. Please tell me how to get segfault error. It is hard to debug the large code if I don't get any error.
Related: How to get back plain old "Segmentation fault" message in windows?
Let's see the assembly:
-O0: (No optimizations,gcc, just a bit stripped):
main:
pushq %rbp #Push address to stack
movq %rsp, %rbp
movl $0, %eax
call main
movl $0, %eax
popq %rbp
ret
You just call a function recursively, always pushing the return address to the stack. But after some implementation/platform defined number of calls there is another memory. You just overwrite it or you access invalid memory. (Segmentation fault)
You can see it like this:
High=======Lower addresses
[stack].....[someOtherMemory]
...recursive call...
[stack ]...[someOtherMemory]
...recursive call...
[stack ].[someOtherMemory]
...recursive call...
[stack ]someOtherMemory]
Kaboom: You accessed the other memory, that was maybe not writable/readable => Crash
Now, you can compile with higher optimizations: -O3, example output, stripped again:
main:
jmp main
It is just an infinite loop. Theoretically both would have the same result. The compiler is nearly allowed to do anything, as long as the observable output stays the same (See: https://stackoverflow.com/a/46455917/13912132).
But in the first, it is translated "literally", leading to hitting other parts. But if no other parts would be hit, it would run all the time.
In the second, the compiler may see, that this would run infinite theoretically, so it got optimized.

GCC instruction relative addressing

The following code worked just fine in gcc6.2:
int main(){
long x, y = 0;
__asm__ (
".data\n\t"
"var_0: .byte 2\n\t"
".text\n\t"
"xor %%eax, %%eax\n\t"
"leaq var_0(%%rax), %%rbx\n\t"
"movb var_0(%%rax), %%al\n\t"
"movq %%rax, %0\n\t"
"movq %%rbx, %1\n\t"
:"=m" (x), "=m" (y)
:
:"%rax", "%rbx"
);
printf("%x %x\n",x, y);
}
Sample output of this is 2 601031. This syntax suggests to me that gcc (or gas I suppose) uses instruction relative addressing. If I replace the above lines with
"leaq var_0(%%rip), %%rbx\n\t"
"movb var_0(%%rip), %%al\n\t"
then the output is again 2 601031 (EDIT: previous statement was incorrect as I had the output of slightly different code). I don't know where this is documented but it's great. However, when I upgraded to gcc6.3, the RIP relative addressing version still works fine but the instruction relative version produces the error
/usr/bin/ld: /tmp/cc2E9Upc.o: relocation R_X86_64_32S against `.data' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
even if I recompile with gcc -fPIC. Could someone tell me what's going on between the two versions of gcc? Are there any changes I need to be aware of? Flags that I need to be using?
EDIT 2: PLaying around with objdump has made it clear to me that the title is nonsense. Gcc6.2 simply uses the translated address of var_0 in the executable. I would like to know why this doesn't work with gcc4.3 while I apologize for the hastily written title.

How to set gcc or clang to use Intel syntax permanently for inline asm() statements?

I have the following code which compiles fine with the gcc command gcc ./example.c. The program itself calls the function "add_two" which simply adds two integers. To use the intel syntax within the extended assembly instructions I need to switch at first to intel and than back to AT&T. According to the gcc documentation it is possible to switch to intel syntax entirely by using gcc -masm=intel ./exmaple.
Whenever I try to compile it with the switch -masm=intel it won't compile and I don't understand why? I already tried to delete the instruction .intel_syntax but it still don't compile.
#include <stdio.h>
int add_two(int, int);
int main(){
int src = 3;
int dst = 5;
printf("summe = %d \n", add_two(src, dst));
return 0;
}
int add_two(int src, int dst){
int sum;
asm (
".intel_syntax;" //switch to intel syntax
"mov %0, %1;"
"add %0, %2;"
".att_syntax;" //switch to at&t syntax
: "=r" (sum) //output
: "r" (src), "r" (dst) //input
);
return sum;
}
The error message by compiling the above mentioned program with gcc -masm=intel ./example.c is:
tmp/ccEQGI4U.s: Assembler messages:
/tmp/ccEQGI4U.s:55: Error: junk `PTR [rbp-4]' after expression
/tmp/ccEQGI4U.s:55: Error: too many memory references for `mov'
/tmp/ccEQGI4U.s:56: Error: too many memory references for `mov'
Use -masm=intel and don't use any .att_syntax directives in your inline asm. This works with GCC and I think ICC, and with any constraints you use. Other methods don't. (See Can I use Intel syntax of x86 assembly with GCC? for a simple answer saying that; this answer explores exactly what goes wrong, including with clang 13 and earlier.)
That also works in clang 14 and later. (Which isn't released yet but the patch is part of current trunk; see https://reviews.llvm.org/D113707).
Clang 13 and earlier would always use AT&T syntax for inline asm, both in substituting operands and in assembling as op src, dst. But even worse, clang -masm=intel would do that even when taking the Intel side of an asm template using dialect-alternatives like asm ("add {att | intel}" : ... )`!
clang -masm=intel did still control how it printed asm after its built-in assembler turned an asm() statement into some internal representation of the instruction. e.g. Godbolt showing clang13 -masm=intel turning add %0, 1 as add dword ptr [1], eax, but clang trunk producing add eax, 1.
Some of the rest of this answer talking about clang hasn't been updated for this new clang patch.
Clang does support Intel-syntax inside MSVC-style asm-blocks, but that's terrible (no constraints so inputs / outputs have to go through memory.
If you were hard-coding register names with clang, -masm=intel would be usable (or the equivalent -mllvm --x86-asm-syntax=intel). But it chokes on mov %eax, 5 in Intel-syntax mode so you can't let %0 expand to an AT&T-syntax register name.
-masm=intel makes the compiler use .intel_syntax noprefix at the top of its asm output file, and use Intel-syntax when generating asm from C outside your inline-asm statement. Using .att_syntax at the bottom of your asm template breaks the compiler's asm, hence the error messages like PTR [rbp-4] looking like junk to the assembler (which is expecting AT&T syntax).
The "too many operands for mov" is because in AT&T syntax, mov eax, ebx is a mov from a memory operand (with symbol name eax) to a memory operand (with symbol name ebx)
Some people suggest using .intel_syntax noprefix and .att_syntax prefix around your asm template. That can sometimes work but it's problematic. And incompatible with the preferred method of -masm=intel.
Problems with the "sandwich" method:
When the compiler substitutes operands into your asm template, it will do so according to -masm=. This will always break for memory operands (the addressing-mode syntax is completely different).
It will also break with clang even for registers. Clang's built-in assembler does not accept %eax as a register name in Intel-syntax mode, and doesn't accept .intel_syntax prefix (as opposed to the noprefix that's usually used with Intel-syntax).
Consider this function:
int foo(int x) {
asm(".intel_syntax noprefix \n\t"
"add %0, 1 \n\t"
".att_syntax"
: "+r"(x)
);
return x;
}
It assembles as follows with GCC (Godbolt):
movl %edi, %eax
.intel_syntax noprefix
add %eax, 1 # AT&T register name in Intel syntax
.att_syntax
The sandwich method depends on GAS accepting %eax as a register name even in Intel-syntax mode. GAS from GNU Binutils does, but clang's built-in assembler doesn't.
On a Mac, even using real GCC the asm output has to assemble with an as that's based on clang, not GNU Binutils.
Using clang on that source code complains:
<source>:2:35: error: unknown token in expression
asm(".intel_syntax noprefix \n\t"
^
<inline asm>:2:6: note: instantiated into assembly here
add %eax, 1
^
(The first line of the error message didn't handle the multi-line string literal very well. If you use ; instead of \n\t and put everything on one line the clang error message works better but the source is a mess.)
I didn't check what happens with "ri" constraints when the compiler picks an immediate; it will still decorate it with $ but IDK if GAS silently ignores that, too, in Intel syntax mode.
PS: your asm statement has a bug: you forgot an early-clobber on your output operand so nothing is stopping the compiler from picking the same register for the %0 output and the %2 input that you don't read until the 2nd instruction. Then mov will destroy an input.
But using mov as the first or last instruction of an asm-template is usually also a missed-optimization bug. In this case you can and should just use lea %0, [%1 + %2] to let the compiler add with the result written to a 3rd register, non-destructively. Or just wrap the add instruction (using a "+r" operand and an "r", and let the compiler worry about data movement.) If it had to load the value from memory anyway, it can put it in the right register so no mov is needed.
PS: it's possible to write inline asm that works with -masm=intel or att, using GNU C inline asm dialect alternatives. e.g.
void atomic_inc(int *p) {
asm( "lock add{l $1, %0 | %0, 1}"
: "+m" (*p)
:: "memory"
);
}
compiles with gcc -O2 (-masm=att is the default) to
atomic_inc(int*):
lock addl $1, (%rdi)
ret
Or with -masm=intel to:
atomic_inc(int*):
lock add DWORD PTR [rdi], 1
ret
Notice that the l suffix is required for AT&T, and the dword ptr is required for intel, because memory, immediate doesn't imply an operand-size. And that the compiler filled in valid addressing-mode syntax for both cases.
This works with clang, but only the AT&T version ever gets used.
Note that -masm= also affects the default inline assembler syntax:
Output assembly instructions using selected dialect. Also affects
which dialect is used for basic "asm" and extended "asm". Supported
choices (in dialect order) are att or intel. The default is att.
Darwin does not support intel.
That means that your first .intel_syntax directive is superfluous and the final .att_syntax is wrong because your GCC call compiles C to Intel assembler code.
IOW, either stick to -masm=intel or sandwich your inline Intel assembler code sections between .intel_syntax noprefix and .att_syntax prefix directives - but don't do both.
Note that the sandwich method isn't compatible with all inline assembler constraints - e.g. a constraint that involves m (i.e. memory operand) would insert an operand in ATT syntax which would yield an error like 'Error: junk (%rbp) after expression'. In those cases you have to use -masm=intel.

Need to convert old 32-bit GAS code to a current GAS assembler (pushfl/popl)

I am in the process of trying to compile an old project on my modern machine. I know this old project used an old (2.x) version of GCC/GAS so I need to clean it up so that I can compile it with a current version.
The code in question:
__get_flags:
pushfl
popl %eax
ret
gas complains that pushfl is not an instruction. From what I read this is an old deprecated GNU mnemonic, but there must be some sort of x86_64 equivalent, surely?
In addition to answering how to convert this code to x86_64 gas, it would be great if someone could explain where mnemonics like pushfl and pushfq and defined and documented. I am quite sure that are GAS creations...
Note: I want to compile this on gcc 4.6.1 and gas 2.21
The following:
static inline u16 __get_flags(void) {
u16 flags;
asm ("pushf\n\t"
"pop %0" : : "+r"(flags) : "cc");
return flags;
}
should actually be portable for both 64/32bit, x64/x86. But it only gets you the condition codes, not the high parts of the state register. If you require the entire contents of the flags register when running in 64bit (long) mode, use the PUSHFQ instruction name, with a u64 (or other 64bit quantity) operand.
I can't add a comment to the answer because I don't have 50 reputation. Anyway:
In the answer:
"pop %0" : : "+r"(flags) : "cc");
Should read:
"pop %0" : "=r"(flags) : : "cc");
Because the syntax is asm( code : outputs : inputs : clobbers ) and what you want is flags to be a register that's output from the asm block, not used as input. (I tested this and it worked for me, I also used 64-bit ints)

GCC Calling label as a function

All is in the title.
For some reasons I have to do it like this.
But when I compile my code, GCC (or GAS maybe...) displays the following error:
.../Temp/cc1C1fjs.s:19: Error: immediate operand illegal with absolute jump
Code:
int main ( int argc, char **argv )
{
/* Some code */
( (void(*)()) &&label)();
/* Some code */
return 0;
label:
asm ("push %ebp");
asm ("mov %esp,%ebp");
/* Some code */
printf("Hello world");
asm ("leave");
asm("ret");
}
I'm sure that this should works because I tried to create a thread using CreateThread function (I'm under windows) specifing as entry point the address of label, and it works perfectly well.
So how can I ensure that the compiler accepting this syntax?
Or there is anothers ways for doing that?
I don't have a solution for you, but I do have a couple of suggestions:
Run gcc -S file.c and look at line #19 to see if you can spot what the actual problem is.
Look through the rest of the (short) .s file to see if anything is obviously amiss. For example, my version of gcc seems to decide that everything after return 0 is dead code, so none of your asm code nor the printf actually make it to the assembler.
Can't this code be moved into a function? This way you'll get the prologue/epilogue for free; taking the address would also be less fraught with difficulty.
I fixed a part of the problem:
#aix you have right, GCC remove
everything of the main function
after return 0;, I fixed this
replacing it by
asm("leave");
asm("xor %eax,%eax");
asm("ret");
Now the code after my label is generated.
Running gcc -S file.c then
gcc file.s -o file.exe, of course it displays the error and at
the error line there is call *$L2
(L2 is label in my c file). It works
by replacing it by call L2.
Now the code after my label and after my call in main is
executed and the program properly
terminates with state 0.
But I don't want to have to do that each time I will compile.
Is it normal that GCC write call *$L2 rather than call L2?

Resources