Executed shellcode terminates main program - c

I am trying to execute shellcode in a memory region. While it works so far, I am confronted with another problem right now: The main-c-program exits after I called the shellcode-program. Is there a (simple) way around this other than working with threads?
I think that this has something to do with the mov rax, 60 and the following syscall, exiting the program. Right?
Main-C-Code
#include <string.h>
#include <sys/mman.h>
const char shellcode[] = "\xeb\x1e\xb8\x01\x00\x00\x00\xbf\x01\x00\x00\x00\x5e\xba\x0d\x00\x00\x00\x0f\x05\xb8\x3c\x00\x00\x00\xbf\x00\x00\x00\x00\x0f\x05\xe8\xdd\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21";
// Error checking omitted for expository purposes
int main(int argc, char **argv)
{
// Allocate some read-write memory
void *mem = mmap(0, sizeof(shellcode), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
// Copy the shellcode into the new memory
memcpy(mem, shellcode, sizeof(shellcode));
// Make the memory read-execute
mprotect(mem, sizeof(shellcode), PROT_READ|PROT_WRITE|PROT_EXEC);
// Call the shellcode
void (*func)();
func = (void (*)())mem;
(void)(*func)();
// This text will never appear
printf("This text never appears");
// Now, if we managed to return here, it would be prudent to clean up the memory:
// (I think that this line of code is also never reached)
munmap(mem, sizeof(shellcode));
return 0;
}
Basis of the Shellcode (assembler (Intel))
global _start
_start:
jmp message
code:
mov rax, 1
mov rdi, 1
pop rsi
mov rdx, 13
syscall
mov rax, 60
mov rdi, 0
syscall
message:
call code
db "Hello, World!"

imo the simplest way would be to make a binary file, then exec() that. and if you need output from that then setup pipes.

I actually found it out by myself. If anyone is interested, the simple solution was to alter the assembler-code as follows:
global _start
_start:
jmp message
code:
mov rax, 1
mov rdi, 1
pop rsi
mov rdx, 13
syscall
ret # Instead of "mov.., mov..., syscall"
message:
call code
db "Hello, World!"

Related

Return from Shellcode instead of exit

I'm working on a shared mem assignment for uni and I've 'borrowed' and 'massaged' some shellcode I've seen in posts I've read here and other places. I've been able to construct an example that runs on my MacBook (Mojave) and almost does what I want.
However, since I'm not that experienced with assembly programming in an OS environment (MacOS in this case), and because I don't fully understand the assembly below, I need a little help to overcome my last issue.
In my C boilerplate wrapper, I have a loop that calls my shellcode periodically, but the loop only executes one iteration. This leads me to the conclusion that the second syscall (in the code below) is performing an exit 0, thus terminating the process.
How can I modify the assembly to return instead of exit?
Note if asked, I can post more information about the wrapper code and tools I'm using.
bits 64
Section .text
global start
start:
jmp short MESSAGE ;00000000 EB24 jmp short 0x26
GOBACK:
mov eax, 0x2000004 ;00000002 B804000002 mov eax,0x2000004 ; write
mov edi, 0x1 ;00000007 BF01000000 mov edi,0x1
lea rsi, [rel msg] ;0000000C 488D3518000000 lea rsi,[rel 0x2b]
mov edx, 0xf ;00000013 BA0F000000 mov edx,0xf
syscall ;00000018 0F05 syscall
mov eax,0x2000001 ;0000001A B801000002 mov eax,0x2000001 ;exit
mov edi,0x0 ;0000001F BF00000000 mov edi,0x0
syscall ;00000024 0F05 syscall
MESSAGE:
call GOBACK
msg: db "Hello, world!", 0dh, 0ah
.len: equ $ - msg
Here is my C boilerplate code, which includes the shellcode from above.
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
const char shellcode[] = "\xeb\x24\xb8\x04\x00\x00\x02\xbf\x01\x00\x00\x00\x48\x8d\x35\x18\x00\x00\x00\xba\x0f\x00\x00\x00\x0f\x05\xb8\x01\x00\x00\x02\xbf\x00\x00\x00\x00\x0f\x05\xe8\xd7\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x20\x77\x6f\x72\x6c\x64\x21\x0d\x0a";
int main(int argc, char **argv)
{
void *mem = mmap(0, sizeof(shellcode), PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
memcpy(mem, shellcode, sizeof(shellcode));
mprotect(mem, sizeof(shellcode), PROT_READ|PROT_WRITE|PROT_EXEC);
for (int i = 0; i < 10; i++) {
int (*func)();
func = (int (*)())mem;
(int)(*func)();
sleep(5);
}
munmap(mem, sizeof(shellcode));
return 0;
}
I have a loop that calls my shellcode
So if it's an actual call then you are good to go and the only change you need to do is to remove the 3 last instructions (mov, mov and syscall) and replaced them with a ret since the return address will be on the stack already. But we need to additionally clean up the stack a little bit since the address of the text string is put there for the sake of syscall, we want to get rid of it before the return.
Also since you shellcode contains an offset (the first jmp opcode with the value of 0x24) it's safer to not delete anything (as it will change the offsets) but to replace with NOP. Unless you modify the shellcode's source code and generate it every time - than it's fine to remove stuff.
So what I would actually propose to do is to replace the bytes that constitutes for the last 3 opcodes with 0x90(NOP) and the last 2 bytes from that replace with pop rax\ret so bytes 0x58 and 0xc3. The final shellcode could look like this:
const char shellcode[] = "\xeb\x24\xb8\x04\x00\x00\x02\xbf\x01\x00\x00\x00\x48\x8d\x35\x18\x00\x00\x00\xba\x0f\x00\x00\x00\x0f\x05\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x58\xc3\xe8\xd7\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x20\x77\x6f\x72\x6c\x64\x21\x0d\x0a";

Why do GDB and different assemblers give different and wrong jmp addresses?

I wanted to run this assembly jmp 0x8048540 in the C code (below) to run a function located at memory address 0x8048540. But I got seg fault. I decided to see where I went wrong...
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#define AMOUNT_OF_STUFF 10
//TODO: Ask IT why this is here
void win(){
system("/bin/cat ./flag.txt");
}
void vuln(){
char * stuff = (char *)mmap(NULL, AMOUNT_OF_STUFF, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
if(stuff == MAP_FAILED){
printf("Failed to get space. Please talk to admin\n");
exit(0);
}
printf("Give me %d bytes:\n", AMOUNT_OF_STUFF);
fflush(stdout);
int len = read(STDIN_FILENO, stuff, AMOUNT_OF_STUFF);
if(len == 0){
printf("You didn't give me anything :(");
exit(0);
}
void (*func)() = (void (*)())stuff;
func();
}
int main(int argc, char*argv[]){
printf("My mother told me to never accept things from strangers\n");
printf("How bad could running a couple bytes be though?\n");
fflush(stdout);
vuln();
return 0;
}
This is the function at the address:
Dump of assembler code for function win:
0x08048540 <+0>: push %ebp
0x08048541 <+1>: mov %esp,%ebp
0x08048543 <+3>: sub $0x8,%esp
0x08048546 <+6>: sub $0xc,%esp
0x08048549 <+9>: push $0x8048700
0x0804854e <+14>: call 0x80483f0 <system#plt>
0x08048553 <+19>: add $0x10,%esp
0x08048556 <+22>: leave
0x08048557 <+23>: ret
End of assembler dump.
I noticed that the opcode that my assemblers gave me were inconsistent. The jump addresses they gave me were also different from the intended address of 0x8048540.
According to defuse.ca for x86, my string literal is \xE9\x3C\x85\x04\x08. The address I see is 0x804853C
However, according to rasm2 for x86, my string literal is \xe9\x3b\x85\x04\x08. The address I see is 0x804853B
1st Qn: Why are the addresses different from my intended address and so different from each other? They were both supposed to give opcode for x86.
Nevertheless, I just decided to go with rasm2's opcode.
Then, I noticed something weird in GDB. (Note: the read() command reads 10 bytes to the memory address 0xf7fd3000.
(gdb) x/8x 0xf7fd3000
0xf7fd3000: 0xe9 0x3b 0x85 0x04 0x08 0x00 0x00 0x00
Seems all well and good so far. The value in the memory address matches the string literal given by rasm2.
Then I decided to see the memory in terms of instructions:
(gdb) x/2i 0xf7fd3000
0xf7fd3000: jmp 0x1b540
0xf7fd3005: add BYTE PTR [eax],al
Woah. Why jump to address 0x1b540?? Could it just be a visual error?
So I ran it.
But GDB REALLY jumped to that address!
(gdb) si
0x0001b540 in ?? ()
=> 0x0001b540: Cannot access memory at address 0x1b540
I thought perhaps I made a mistake. Perhaps jmp 0x8048540 is illegal. But, according to this source, jmp accepts 32 bit pointers.
2nd Qn: Why is GDB giving me such a ridiculous address?
Could someone kindly enlighten me the reason behind the different addresses? All I want is just to jump to 0x8048540. defuse.ca gave me 0x804853C, rasm2 gave me 0x804853B, and GDB gave me 0x1b540. T.T
Thank you.
FYI, this is from Shells challenge in PicoCTF 2017.
The machine code for "jmp 0x8048540" is the input.
That's wrong:
There are different kinds of jmp instructions (like jmp ecx which takes the destination address from the ecx register) on x86 CPUs.
The jump instructions (jmp, call, je, jae ...) which take an immediate value however are PC-relative:
The destination address of the jump is calculated by the formula:
argument of "jmp" + address of the next instruction
So the following code:
0x12340000 E9 00 00 01 00
Disassembles to:
0x12340000 jmp 0x12350005
This is calculated the following way:
The jmp instruction is 5 bytes long and it is located at address 0x12340000. So the next instruction (the instruction following jmp) is located at 0x12340005.
The argument of jmp is 0x10000 and 0x12340005 + 0x10000 = 0x12350005.
And of course: The instruction will not only disassemble like this but also jump to 0x12350005.

EggHunter not finding the egg, causing infinite loop

EggHunter not finding the egg (32bit), causing infinite loop
I have 1 example, that prints We found the egg! which works, and another the prints Hello egg! that isn't working.
Both use the same egg 0x90f890f9
I think the problem may be here:
cmp dword [ecx], 0x90f890f9 ; marker
Here is the c code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
unsigned char egghunter[21];
void main()
{
/* works OK (We found the egg!)
"\x90\xf9\x90\xf8\x90\x68\x21\x0a\x0a\x0a\x68\x20\x65\x67\x67\x68\x20\x74\x68"
"\x65\x68\x6f\x75\x6e\x64\x68\x57\x65\x20\x66\x31\xc9\xb1\x12\x51\xb8"
"\x11\x11\x51\x08\x50\x31\xc0\x50\x54\x51\x89\xe6\x83\xc6\x14\x03\x74"
"\x24\x10\x2b\x34\x24\x56\x89\xf1\xeb\x1c\xeb\x0c\x59\x59\xe2\xe8\x31"
"\xdb\x31\xc0\xb0\x01\xcd\x80\x31\xc0\xb0\xa2\x8d\x5c\x24\x0c\x31\xc9"
"\xcd\x80\xeb\xe6\x31\xd2\xb2\x01\x31\xdb\xb3\x01\x31\xc0\xb0\x04\xcd"
"\x80\xeb\xd4";
*/
/* gives an infinite loop (suppose to print Hello egg!)
"\x90\xf9\x90\xf8\x90\xeb\x17\x31\xc0\xb0\x04\x31\xdb\xb3\x01\x59\x31\xd2\xb2\x0b\xcd\x80"
"\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe4\xff\xff\xff\x48\x65\x6c\x6c"
"\x6f\x20\x65\x67\x67\x21\x0a";
*/
unsigned char shellcode[256] = \
"\x90\xf9\x90\xf8\x90\xeb\x17\x31\xc0\xb0\x04\x31\xdb\xb3\x01\x59\x31\xd2\xb2\x0b\xcd\x80"
"\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe4\xff\xff\xff\x48\x65\x6c\x6c"
"\x6f\x20\x65\x67\x67\x21\x0a";
printf("Shellcode: %d bytes\n", strlen(shellcode));
strcpy(egghunter,"\xeb\x0e\x59\x83\xe9\x17\x81\x39\xf9\x90\xf8\x90\xe0\xf8\xff\xe1\xe8\xed\xff\xff\xff");
printf("Egghunter: %d bytes\n", strlen(egghunter));
int (*ret)() = (int(*)())egghunter;
ret();
}
Here is the egghunter code:
global _start
section .text
_start:
jmp call_egghunter
egghunter:
pop ecx ; save addr ptr
sub ecx, 23 ; move addr ptr back
next:
cmp dword [ecx], 0x90f890f9 ; marker
loopnz next ; dec ecx, jump
jmp ecx ; jump to shellcode
call_egghunter:
call egghunter
And the hello egg code that isn't working is:
global _start
section .text
_start:
jmp short call_shellcode
shellcode:
; print hello world on the screen
xor eax, eax
mov al, 0x4
xor ebx, ebx
mov bl, 0x1
pop ecx
xor edx, edx
mov dl, 11
int 0x80
; exit the program gracefully
xor eax, eax
mov al, 0x1
xor ebx, ebx
int 0x80
call_shellcode:
call shellcode
message: db "Hello egg!", 0xA
Your egghunter is a global variable which lives in the data section. Your shellcode is a local variable which lives on the stack. You search for the mark from egghunter downwards, however the usual layout on linux (which I assume you use due to the int 0x80) places the stack above the data section. As such, you are searching in the wrong direction, and whatever you are finding is not your shellcode. In fact, it is part of the code that does the strcpy(egghunter, literal):
0x80494fe: movl $0x90f890f9,0x80497d0
0x8049508: movl $0xe1fff8e0,0x80497d4
0x8049512: movl $0xffffede8,0x80497d8
0x804951c: movw $0xff,0x80497dc
0x8049525: movl $0x80497c8,(%esp)
Learn to use a debugger so you can step through the code and see what it is doing.

gdb can't access memory address error

here is my disas code:
0x0804844d <+0>: push %ebp
0x0804844e <+1>: mov %esp,%ebp
0x08048450 <+3>: and $0xfffffff0,%esp
0x08048453 <+6>: sub $0x20,%esp
0x08048456 <+9>: movl $0x8048540,(%esp)
0x0804845d <+16>: call 0x8048310 <puts#plt>
0x08048462 <+21>: lea 0x1c(%esp),%eax
0x08048466 <+25>: mov %eax,0x4(%esp)
0x0804846a <+29>: movl $0x8048555,(%esp)
0x08048471 <+36>: call 0x8048320 <scanf#plt>
0x08048476 <+41>: mov 0x1c(%esp),%eax
0x0804847a <+45>: cmp $0x208c,%eax
0x0804847f <+50>: jne 0x804848f <main+66>
0x08048481 <+52>: movl $0x8048558,(%esp)
0x08048488 <+59>: call 0x8048310 <puts#plt>
0x0804848d <+64>: jmp 0x804849b <main+78>
=> 0x0804848f <+66>: movl $0x8048569,(%esp)
0x08048496 <+73>: call 0x8048310 <puts#plt>
0x0804849b <+78>: mov $0x0,%eax
0x080484a0 <+83>: leave
0x080484a1 <+84>: ret
what i'm tring to examine is $0x208c. When I type x/xw 0x208c it gives me back error which says Cannot access memory at address 0x208c. When i type Info registers and look at eax it says the value which i provided. So basically this program compares two values and depending on that prints something out.The problem is that this is homework from university and I have not got code. Hope you can help. Thank you.
When I type x/xw 0x208c it gives me back error which says Cannot access memory at address 0x208c
The disassembly for your program says that it does something like this:
puts("some string");
int i;
scanf("%d", &i); // I don't know what the actual format string is.
// You can find out with x/s 0x8048555
if (i == 0x208c) { ... } else { ... }
In other words, the 0x208c is a value (8332) that your program has hard-coded in it, and is not a pointer. Therefore, GDB is entirely correct in telling you that if you interpret 0x208c as a pointer, that pointer does not point to readable memory.
i finally figured out to use print statement instead of x/xw
You appear to not understand the difference between print and examine commands. Consider this example:
int foo = 42;
int *pfoo = &foo;
With above, print pfoo will give you the address of foo, and x pfoo will give you the value stored at that address (i.e. the value of foo).
I found out that it is impossible to examine mmaped memory that does not have PROT_READ flag. This is not the OPs problem, but it was mine, and the error message is the same.
Instead of
mmap(0, size, PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
do
mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
and voila, the memory can be examined.
Uninitialized pointers
It is kind of obvious in retrospective, but this is what was causing GDB to show that error message to me. Along:
#include <stdio.h>
int main(void) {
int *p;
printf("*p = %d\n", *p);
}
And then:
gdb -q -nh -ex run ./tmp.out
Reading symbols from ./tmp.out...done.
Starting program: /home/ciro/bak/git/cpp-cheat/gdb/tmp.out
Program received signal SIGSEGV, Segmentation fault.
0x0000555555554656 in main () at tmp.c:5
5 printf("*p = %d\n", *p);
(gdb) print *p
Cannot access memory at address 0x0
But in a complex program of course, and where the address was something random different from zero.
In my case the problem was caused by calling munmap with length bigger than mmap:
#include <errno.h>
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
int main(){
size_t length_alloc = 10354688;
size_t length_unmap = 5917171456;
void *v = mmap(0, 10354688, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (v == MAP_FAILED) {
printf("mmap of %lu bytes failed with error: %s", 10354688, strerror(errno));
}else{
printf("mmaped %p\n", v);
munmap(v, length_unmap);
}
}
So the unmap unmapped also mappings for stacks of a few threads. Pretty nasty one because it rendered the core dump impossible to use with my current skill level. Especially that in the original problem, the size passed to munmap was somewhat random. And it crashed only sometimes and the end of a very lengthy process.
If GDB says memory address not found that means the symbol is not available in the executable file opened by gdb or through file exefilename. OR you have not compiled the exefile with -g option. What happens when you are a newbie for gdb you may have given the command file argfile instead of run argfile. Pls check.
I experienced same error. I solved my case with increasing swap space with Gparted software.
1- First install Gparted with "sudo apt-get install gparted"
2- Open Gparted and right click on swap then select Resize/Move
(Note: you be able to increase swap size only if you have unallocated memory before or after swap memory)

Modify C code with buffer overflow vulnerability to skip code [duplicate]

This question already has answers here:
C Code how to change return address in the code?
(3 answers)
Closed 7 years ago.
I'm trying to find a way to exploit the buffer overflow vulnerability in the following source code so the line, printf("x is 1") will be skipped:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void func(char *str) {
char buffer[24];
int *ret;
strcpy(buffer,str);
}
int main(int argc, char **argv) {
int x;
x = 0;
func(argv[1]);
x = 1;
printf("x is 1");
printf("x is 0");
getchar();
}
In order to do this, I want to modify the "func" function. I know that I will need to use the ret variable in order to modify the return address to just past the line I want to skip, but I'm not sure how to actually do that. Does anyone have a suggestion?
EDIT:
By using gdb, I was able to find the following calls in the main function:
Temporary breakpoint 1, 0x00000000004005ec in main ()
(gdb) x/20i $pc
=> 0x4005ec <main+4>: sub $0x20,%rsp
0x4005f0 <main+8>: mov %edi,-0x14(%rbp)
0x4005f3 <main+11>: mov %rsi,-0x20(%rbp)
0x4005f7 <main+15>: movl $0x0,-0x4(%rbp)
0x4005fe <main+22>: mov -0x20(%rbp),%rax
0x400602 <main+26>: add $0x8,%rax
0x400606 <main+30>: mov (%rax),%rax
0x400609 <main+33>: mov %rax,%rdi
0x40060c <main+36>: callq 0x4005ac <func>
0x400611 <main+41>: movl $0x1,-0x4(%rbp)
0x400618 <main+48>: mov $0x4006ec,%edi
0x40061d <main+53>: mov $0x0,%eax
0x400622 <main+58>: callq 0x400470 <printf#plt>
0x400627 <main+63>: mov $0x4006f3,%edi
0x40062c <main+68>: mov $0x0,%eax
0x400631 <main+73>: callq 0x400470 <printf#plt>
0x400636 <main+78>: callq 0x400490 <getchar#plt>
0x40063b <main+83>: leaveq
0x40063c <main+84>: retq
0x40063d: nop
Although, I'm confused as of where to go from here. I know that the function will return to the line of 0x400611 and that I need to cause it to jump to 0x400631, but I'm not sure how to determine how many bits to jump or how I should be modifying the ret variable.
The idea is to find where the return address to the main function is on the stack and then add to this address the offset to the command you'd like to get.
To do that:
Use the disassembly to find the difference between the original return address and the new one:
Find the func frame address on the stack using a local variable (e.g. the function parameter):
Finally find the relative location of the return address on the stack comparing the address of the local variable:
Using the above your code would look something like:
void func(char *str) {
// 1. Get the address of an object on the stack
long *ret = (long*)(&str);
// 2. Move ret to point to the location of the return address from this function.
// Per the example above on my system (Windows 64bit + VS) it was just -1
ret -= NUMBER_OF_ITEMS_IN_THE_STACK_BEFORE_RETURN_ADDR;
// 3. Modify the return address by adding it the offset to command to go to (in my
// (case 33).
*ret = *ret + OFFSET_TO_COMMAND;
// The rest of your code
char buffer[24];
strcpy(buffer, str);
}
As noted above, the exact numbers are system dependent (i.e. OS, Compiler, etc.). However, using the techniques above you should be able to find the right numbers to set.
As a final note, modern compilers (e.g. VS) may have security guards for protecting stack corruption. If your program crashed because of it check in your compiler options how this option can be disabled.

Resources