Page 1 of 2

change the return address to point to shellcode

Posted: Thu Oct 09, 2014 9:50 am
by hadi
Im using linux and I have c program, I would like to change the return
address to point to my shellcode, im unable to do it.
Can someone point to me how to do it with linux gdb debugger.

Here is my shellcode

"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc
2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"

Here is my c program

int global_value = 0;
void bang(int val)
{
if (global_value == cookie) {
printf("Bang!: You set global_value to 0x%x\n", global_value);
validate(2);
} else
printf("Misfire: global_value = 0x%x\n", global_value);
exit(0);
}

Re: change the return address to point to shellcode

Posted: Thu Oct 09, 2014 10:17 am
by Brynet-Inc
This has nothing to do with operating system development, besides possessing an understanding of x86 instruction opcode encodings.

Re: change the return address to point to shellcode

Posted: Thu Oct 09, 2014 10:35 am
by hadi
thank you Brynet-Inc for your reply.
i understand that it has nothing to do with O/S.
but what i want to change the return address of the function to my shellcode.
can you please give me example how to do it.? with my source code.

Re: change the return address to point to shellcode

Posted: Thu Oct 09, 2014 10:42 am
by iansjack
Perhaps you could explain why you want to do this. What are you trying to achieve?

Re: change the return address to point to shellcode

Posted: Thu Oct 09, 2014 10:45 am
by iocoder
If I get you correctly, you can change the return address of bang by modifying the pushed IP in the stack... in gcc (x86_64) it would be something like this:

Code: Select all

__asm__("movq $my_shell_code, 8(%rbp)");

Re: change the return address to point to shellcode

Posted: Thu Oct 09, 2014 11:01 am
by hadi
thank you iocoder for your reply.

but im using 32 bit O/S.

can you explain more in details. im new to this.

first of all how to get bang return address?
second shell i write assemble code to change bang return address to point to my shellcode ?

Re: change the return address to point to shellcode

Posted: Thu Oct 09, 2014 11:04 am
by hadi
iansjack, im trying to exploit my c code by learning how to change the return address with out supplying buffer.

can you help here..

thank you.

Re: change the return address to point to shellcode

Posted: Thu Oct 09, 2014 11:10 am
by Combuster
1) learn to single step through assembly
2) learn to predict what instructions do
3) read the intel manual on "RET"
4) make that instruction do something else.

Re: change the return address to point to shellcode

Posted: Thu Oct 09, 2014 11:23 am
by hadi
Combuster,

i understand what you saying about learning Assembly.

but what i need now little input about changing my return address to shellcode.

can you help here please....

Re: change the return address to point to shellcode

Posted: Thu Oct 09, 2014 11:24 am
by iansjack
hadi wrote:iansjack, im trying to exploit my c code by learning how to change the return address with out supplying buffer.

can you help here..

thank you.
That tells me nothing that you haven't already said. Why do you want to manipulate return addresses in this way? I can think of nefarious reasons and I wouldn't want to help a proto-hacker.

Re: change the return address to point to shellcode

Posted: Thu Oct 09, 2014 11:24 am
by iocoder
hadi wrote:thank you iocoder for your reply.

but im using 32 bit O/S.

can you explain more in details. im new to this.

first of all how to get bang return address?
second shell i write assemble code to change bang return address to point to my shellcode ?
I don't know about stuff like exploitation and security, but lemme help you with what I know.

Given this simple C program like this:

Code: Select all

#include <stdio.h>
#include <stdlib.h>

int global_value = 0;

void shellcode() {
    __asm__(".byte 0x90,0x90,0x90,0x90"); /* you may put your shellcode here */
    printf("hey guyz!\n");
    exit(0);
}

void bang(int val) {
    if (global_value == 5) {
        printf("Bang!: You set global_value to 0x%x\n", global_value);
        //validate(2);
    } else
        printf("Misfire: global_value = 0x%x\n", global_value);
    //exit(0);
    __asm__("movl $shellcode, 4(%ebp)");
}

int main() {
    bang(0);
}
When translated into assembly using gcc (32-bit):

Code: Select all

	.file	"main.c"
	.globl	global_value
	.bss
	.align 4
	.type	global_value, @object
	.size	global_value, 4
global_value:
	.zero	4
	.section	.rodata
.LC0:
	.string	"hey guyz!"
	.text
	.globl	shellcode
	.type	shellcode, @function
shellcode:
.LFB2:
	.cfi_startproc
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	subl	$8, %esp
#APP
# 7 "main.c" 1
	.byte 0x90,0x90,0x90,0x90
# 0 "" 2
#NO_APP
	subl	$12, %esp
	pushl	$.LC0
	call	puts
	addl	$16, %esp
	subl	$12, %esp
	pushl	$0
	call	exit
	.cfi_endproc
.LFE2:
	.size	shellcode, .-shellcode
	.section	.rodata
	.align 4
.LC1:
	.string	"Bang!: You set global_value to 0x%x\n"
.LC2:
	.string	"Misfire: global_value = 0x%x\n"
	.text
	.globl	bang
	.type	bang, @function
bang:
.LFB3:
	.cfi_startproc
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	subl	$8, %esp
	movl	global_value, %eax
	cmpl	$5, %eax
	jne	.L3
	movl	global_value, %eax
	subl	$8, %esp
	pushl	%eax
	pushl	$.LC1
	call	printf
	addl	$16, %esp
	jmp	.L4
.L3:
	movl	global_value, %eax
	subl	$8, %esp
	pushl	%eax
	pushl	$.LC2
	call	printf
	addl	$16, %esp
.L4:
#APP
# 19 "main.c" 1
	movl $shellcode, 4(%ebp)
# 0 "" 2
#NO_APP
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE3:
	.size	bang, .-bang
	.globl	main
	.type	main, @function
main:
.LFB4:
	.cfi_startproc
	leal	4(%esp), %ecx
	.cfi_def_cfa 1, 0
	andl	$-16, %esp
	pushl	-4(%ecx)
	pushl	%ebp
	.cfi_escape 0x10,0x5,0x2,0x75,0
	movl	%esp, %ebp
	pushl	%ecx
	.cfi_escape 0xf,0x3,0x75,0x7c,0x6
	subl	$4, %esp
	subl	$12, %esp
	pushl	$0
	call	bang
	addl	$16, %esp
	movl	-4(%ebp), %ecx
	.cfi_def_cfa 1, 0
	leave
	.cfi_restore 5
	leal	-4(%ecx), %esp
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE4:
	.size	main, .-main
	.ident	"GCC: (GNU) 4.9.1"
	.section	.note.GNU-stack,"",@progbits
You can see that the main function calls bang(0) by pusing a 0 ("push $0" line) then callingbang ("call bang") line.
The call instruction in x86 in protected mode pushes the EIP into stack (EIP here contains the return address, which points to the instruction directly after the call) then jumps to the destination code. Now at this point the stack has the return address of bang at its top (pointed to by ESP). bang() starts execution.

At first, bang() pushes EBP (the "pushl %ebp" in bang). This simply means that ESP decreases by four. So at this point, the return address becomes at ESP+4. Then comes the "movl %esp, %ebp" so the current value of ESP can be stored into EBP until the function leaves. Based on this information, we can use EBP+4 to get and modify the return address of bang().

The __asm__("movl $shellcode, 4(%ebp)"); in your C code does the trick. now when bang() returns (notice that I disabled exit(0)), it will actually return to the beginning shellcode(), not the "addl.." instruction in main().

Re: change the return address to point to shellcode

Posted: Thu Oct 09, 2014 12:00 pm
by iansjack
Why go through all that if the code is actually included in the program? Just place it after the function call.

I'm reading it that the OP wants to hook some external code into a program. Now why would you want to do that? ;) Actually, modern OSs make this difficult to do - for obvious reasons.

Re: change the return address to point to shellcode

Posted: Thu Oct 09, 2014 12:11 pm
by SpyderTL
The IP register holds the current instruction address. (or EIP if you are in 32-bit mode)

When a function is called using the CALL instruction, the CPU pushes the current value of IP (which just happens to point to the "next" instruction after the CALL instruction) to the stack.

Then when the function is complete, it ends with a RET instruction, and the CPU pulls the "saved" value of IP from the stack and overwrites the IP register with the "saved" value, which causes the CPU to start executing code from the original location.

You can "trick" the CPU into "returning" to a different location by replacing the stored 32-bit address on the top of the stack with a new 32-bit address, and then calling RET.

However, if you are in 32-bit protected mode, the CPU will check and make sure that you have permission to execute code at the new address, and will throw a General Protection Fault if you do not.

Hopefully, this makes sense. If not, feel free to ask any specific questions you may have.

Re: change the return address to point to shellcode

Posted: Thu Oct 09, 2014 12:28 pm
by iocoder
iansjack wrote:Why go through all that if the code is actually included in the program? Just place it after the function call.

I'm reading it that the OP wants to hook some external code into a program. Now why would you want to do that? ;) Actually, modern OSs make this difficult to do - for obvious reasons.
Yeah exactly. The text section in GNU/Linux is usually read-only, and I don't think that other data sections and the stack are executable. But maybe it is easy to do in some older versions of some poor operating system still used by many people.... :D

Re: change the return address to point to shellcode

Posted: Thu Oct 09, 2014 1:07 pm
by hadi
iocoder,

thank you for your help and support.

i can see eip pointing to shellcode (nope) with gdb.

my question here how i can compile shellcode separately with Assembly, and injected into my code with gdb linux debugger .