Can I get RIP address in C? - c

Basically I am trying to get RSP, RBP and RIP addresses into pointers.
Code:
#include <stdio.h>
int main()
{
char buf[500];
int *rsp;
int *rbp;
int *rip;
strcpy(buf, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
ptr = buf;
printf("[buf:%p:%s]\n[rsp:%p:%s]\n", &buf, buf, rsp, rsp);
return 0;
}
The above pointer works just fine while getting the RSP address. But I don't know how to get the RBP and RIP addresses.
Can you tell me how can I point *rbp to RBP address and *rip to RIP address?

Current x86 hardware doesn't work that way, so you cannot get the address of the any register - it just doesn't have one.
What does it mean?
It means you can get the value of each register but you cannot get the address of the registers - they have none.
For instance, if you do at the beginning of a function the following, you'll get the address your RIP is pointing to.
void foo(param a, param b)
{
int dummy;
int* rip = &dummy;
}
But note that you this won't be accessible outside this function.

Related

Buffer Overflow Return Address Attack

I am trying to learn more about buffer overflows so I have created a simple program to gain knowledge and try to exploit it.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void failed(void)
{
puts("Did not exploit");
exit(0);
}
void pass(void)
{
puts("Good Job");
exit(1);
}
void foo()
{
char input[4];
gets(input);
}
int _main()
{
foo();
failed();
return 0;
}
I am trying to fill the buffer within foo() with random characters as well as the address of pass() such that the return address of foo() gets overwritten to the starting address of pass(). Using the GDB commands as follows to get relevant information.
x foo
-> 0x8049dd7 foo : 0xfb1e0ff3
disas foo
Dump of assembler code for function foo:
0x08049e09 <+0>: endbr32
0x08049e0d <+4>: push %ebp
0x08049e0e <+5>: mov %esp,%ebp
0x08049e10 <+7>: push %ebx
0x08049e11 <+8>: sub $0x14,%esp
0x08049e14 <+11>: call 0x8049e5a <__x86.get_pc_thunk.ax>
0x08049e19 <+16>: add $0x9b1e7,%eax
0x08049e1e <+21>: sub $0xc,%esp
0x08049e21 <+24>: lea -0xc(%ebp),%edx
0x08049e24 <+27>: push %edx
0x08049e25 <+28>: mov %eax,%ebx
0x08049e27 <+30>: call 0x8058850 <gets>
0x08049e2c <+35>: add $0x10,%esp
0x08049e2f <+38>: nop
0x08049e30 <+39>: mov -0x4(%ebp),%ebx
0x08049e33 <+42>: leave
0x08049e34 <+43>: ret
End of assembler dump.
I then created a python program which feeds its output into my vulnerable.c program as printing simply
print('A'*15 + '\x08\x04\x9d\xd7')
The A*15 is supposed to fill the buffer and the EBP then overwrites the return address with the address of foo (\x08\x04\x9d\xd7) but I continue to get segmentation faults. Any assistance would be great!
Any mistake and the attempt will segfault. You must:
have the right target address
put it in the right place on the stack
use the right byte order
The first one is difficult because the kernel will randomize address spaces on load,
primarily because of these kinds of attacks.
The other two you've gotten wrong.
If you'd like to play with something similar, here's an example
that changes the return address. Because of C calling conventions,
the stack is corrupted at the end of main, which can be fixed by using
stdcall or pascal calling conventions for the test function.
Syntax for that is compiler dependent.
#include <stdio.h>
#include <stdlib.h>
void oops() {
printf("oops!\n");
}
void /*__stdcall*/ test(int t)
{
/* x86 stack is top down, int is same size as pointer */
int *return_is_at = &t - 1;
/* replace parameter with our return address, for oops to return to */
*(&t) = *return_is_at; /* just-in-case avoid optimization*/
/* replace our return address with address of oops */
*return_is_at = (int)oops;
}
int main(int argc, char **argv)
{
test(1);
printf("test returned\n");
/* unless stdcall, at this point our stack is corrupted
and this return will crash, so:
*/
exit(1);
}
Here's an alternative function that uses a local variable to calculate
the return address location intead of the parameter.
This assumes a standard stack frame, which the compiler may optimize away.
It also corrupts the stack.
void test2()
{
/* x86 stack is top down, int is same size as pointer */
/* this relies on consistently defined stack frames */
int l;
int *return_is_at = &l + 2;
/* copy our return address up one,
for oops to return to (corrupting the stack)
*/
return_is_at[1] = *return_is_at;
/* replace our return address with address of oops */
*return_is_at = (int)oops;
}
FYI - It's possible to use a similar technique to track unique call trees for a function
(by walking up the stack frames) in order to fail specific call instances during testing.

Segmentation fault when calling printf in C after setting the stack

I'am doing an exercice for an Operational Systems class and getting an SegFault error when calling printf with arguments.
The objective of the exercice is to simulate the initialization of a thread and print a counter, not very difficult. I have a table of 4 entries each with size 4096 bytes, each entry must represent the thread's stack represented as
#define STACK_SIZE 4096
char table[4][STACK_SIZE];
I defined a type called coroutine that will get only a stack address
typedef void* coroutine_t;
The i have a initialization code. This code must take the end of the routine stack, append the address of the coroutine and the initialization of the registers and return the pointer that will be the stack pointer for the coroutine.
coroutine_t init_coroutine(void *stack_begin, unsigned int stack_size,
void (*initial_pc)(void)) {
char *stack_end = ((char *)stack_begin) + stack_size;
void **ptr = (void**) stack_end;
ptr--;
*ptr = initial_pc;
ptr--;
*ptr = stack_end; /* Frame pointer */
ptr--;
*ptr = 0; /* RBX*/
ptr--;
*ptr = 0; /* R12 */
ptr--;
*ptr = 0; /* R13 */
ptr--;
*ptr = 0; /* R14 */
ptr--;
*ptr = 0; /* R15 */
return ptr;
}
Then i have this code in x86 assembly to enter the coroutine that just pop the register previously pushed
.global enter_coroutine /* Makes enter_coroutine visible to the linker*/
enter_coroutine:
mov %rdi,%rsp /* RDI contains the argument to enter_coroutine. */
/* And is copied to RSP. */
pop %r15
pop %r14
pop %r13
pop %r12
pop %rbx
pop %rbp
ret /* Pop the program counter */
The rest of my code is this
coroutine_t cr;
void test_function() {
int counter = 0;
while(1) {
printf("counter1: %d\n", counter);
counter++;
}
}
int main() {
cr = init_coroutine(table[0], STACK_SIZE, &test_function);
enter_coroutine(cr);
return 0;
}
So for the error
If i run as it is i will get a segfault when the program call printf the output from gdb is
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7dfcfdd in __vfprintf_internal (s=0x7ffff7f9d760 <_IO_2_1_stdout_>, format=0x555555556004 "counter1: %d\n", ap=ap#entry=0x555555558f48 <table+3848>, mode_flags=mode_flags#entry=0) at vfprintf-internal.c:1385
I assume it has some thing happening with the stack for two causes:
If i just print a string without parameters i get no error
If i remove the first ptr-- statement from the init_coroutine function it will also work, but will alocate things in the end of the stack and hence in the other thread's stack
I'am running this in a Intel(R) Core(TM) i5-5200U CPU with ubuntu 21.10 and ggc version 11.2.0
Could you give me some light here ?
I wasn't able to reproduce the problem on my x86_64 Linux box, but I was on compiler explorer, and the problem seems to be simple stack overflow (i.e., 4096 is too small a stack for printf).
Increasing the stack size (or choosing table[1], table[2], or table[3] instead table[0], which is effectively the same as increasing stack size) appears to make it work: https://gcc.godbolt.org/z/rnfMThbjo

Save CPU registers to variables in GCC

I want get the values in EAX/EBX/ESP/EIP etc. and save them in C variables. For example:
int cEax;
asm("mov cEax,%eax"); ...
You can use this
register int eax asm("eax");
register int eax asm("ebx");
register int eax asm("esp");
//...
int cEax = eax;
int cEbx = ebx;
int cEsp = esp;
//...
You can also work with those registers in an expression just as any other variables or just use that register's value directly without assigning to another variable.
It's more tricky to get eip without inline assembly but in gcc you can get it with __builtin_return_address or the label as values extension.
void* getEIP()
{
return __builtin_return_address(0);
}
void *currentInstruction = getEIP();
currentAddr: void *nextInstruction = &&currentAddr;
If you want inline assembly you can use the way in this page

c generate function and call it

#include <stdio.h>
#define uint unsigned int
#define AddressOfLabel(sectionname,out) __asm{mov [out],offset sectionname};
void* CreateFunction(void* start,void *end) {
uint __start=(uint)start,__end=(uint)end-1
,size,__func_runtime;
void* func_runtime=malloc(size=(((__end)-(__start)))+1);
__func_runtime=(uint)func_runtime;
memcpy((void*)(__func_runtime),start,size);
((char*)func_runtime)[size]=0xC3; //ret
return func_runtime;
}
void CallRuntimeFunction(void* address) {
__asm {
call address
}
}
main() {
void* _start,*_end;
AddressOfLabel(__start,_start);
AddressOfLabel(__end,_end);
void* func = CreateFunction(_start,_end);
CallRuntimeFunction(func); //I expected this method to print "Test"
//but this method raised exception
return 0;
__start:
printf("Test");
__end:
}
CreateFunction - takes two points in memory (function scope), allocate, copy it to the allocated memory and returns it (The void* used like a function to call with Assembly)
CallRuntimeFunction - runs the functions that returns from CreateFunction
#define AddressOfLabel(sectionname,out) - Outs the address of label (sectionname) to variable (out)
When I debugged this code and stepped in the call of CallRuntimeFunction and go to disassembly ,
I saw alot of ??? instead of assembly code of between __start and __end labels.
I tried to copy machine code between two labels and then run it. But I don't have any idea why I can't call function that allocated with malloc.
Edit:
I changed some code and done part of the work.
Runtime Function's memory allocate:
void* func_runtime=VirtualAlloc(0, size=(((__end)-(__start)))+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
Copy from function scope:
CopyMemory((void*)(__func_runtime),start,size-1);
But when I ran this program I can that:
mov esi,esp
push 0E4FD14h
call dword ptr ds:[0E55598h] ; <--- printf ,after that I don't know what is it
add esp,4
cmp esi,esp
call 000B9DBB ; <--- here
mov dword ptr [ebp-198h],0
lea ecx,[ebp-34h]
call 000B9C17
mov eax,dword ptr [ebp-198h]
jmp 000D01CB
ret
At here it enters to another function and weird stuff.
void CallRuntimeFunction(void* address) {
__asm {
call address
}
}
here address is a "pointer" to a parameter of this function which is also a pointer.
pointer to a pointer
use:
void CallRuntimeFunction(void* address) {
_asm {
mov ecx,[address] //we get address of "func"
mov ecx,[ecx] //we get "func"
call [ecx] //we jump func(ecx is an address. yes)
}
}
you wanna call func which is a pointer. when passed in your CallRunt... function, this generates a new pointer to point to that pointer. Pointer of second degree.
void* func = CreateFunction(_start,_end);
yes func is a pointer
Important: check your compilers "calling convention" options. Try the decl one
Be sure to invalidate the caches (both instruction and data) between the function code generation and its calling. See self-modifying code for further info.

How to skip a line doing a buffer overflow in C

I want to skip a line in C, the line x=1; in the main section using bufferoverflow; however, I don't know why I can not skip the address from 4002f4 to the next address 4002fb in spite of the fact that I am counting 7 bytes form <main+35> to <main+42>.
I also have configured the options the randomniZation and execstack environment in a Debian and AMD environment, but I am still getting x=1;. What it's wrong with this procedure?
I have used dba to debug the stack and the memory addresses:
0x00000000004002ef <main+30>: callq 0x4002a4 **<function>**
**0x00000000004002f4** <main+35>: movl $0x1,-0x4(%rbp)
**0x00000000004002fb** <main+42>: mov -0x4(%rbp),%esi
0x00000000004002fe <main+45>: mov $0x4629c4,%edi
void function(int a, int b, int c)
{
char buffer[5];
int *ret;
ret = buffer + 12;
(*ret) += 8;
}
int main()
{
int x = 0;
function(1, 2, 3);
x = 1;
printf("x = %i \n", x);
return 0;
}
You must be reading Smashing the Stack for Fun and Profit article. I was reading the same article and have found the same problem it wasnt skipping that instruction. After a few hours debug session in IDA I have changed the code like below and it is printing x=0 and b=5.
#include <stdio.h>
void function(int a, int b) {
int c=0;
int* pointer;
pointer =&c+2;
(*pointer)+=8;
}
void main() {
int x =0;
function(1,2);
x = 3;
int b =5;
printf("x=%d\n, b=%d\n",x,b);
getch();
}
In order to alter the return address within function() to skip over the x = 1 in main(), you need two pieces of information.
1. The location of the return address in the stack frame.
I used gdb to determine this value. I set a breakpoint at function() (break function), execute the code up to the breakpoint (run), retrieve the location in memory of the current stack frame (p $rbp or info reg), and then retrieve the location in memory of buffer (p &buffer). Using the retrieved values, the location of the return address can be determined.
(compiled w/ GCC -g flag to include debug symbols and executed in a 64-bit environment)
(gdb) break function
...
(gdb) run
...
(gdb) p $rbp
$1 = (void *) 0x7fffffffe270
(gdb) p &buffer
$2 = (char (*)[5]) 0x7fffffffe260
(gdb) quit
(frame pointer address + size of word) - buffer address = number of bytes from local buffer variable to return address
(0x7fffffffe270 + 8) - 0x7fffffffe260 = 24
If you are having difficulties understanding how the call stack works, reading the call stack and function prologue Wikipedia articles may help. This shows the difficulty in making "buffer overflow" examples in C. The offset of 24 from buffer assumes a certain padding style and compile options. GCC will happily insert stack canaries nowadays unless you tell it not to.
2. The number of bytes to add to the return address to skip over x = 1.
In your case the saved instruction pointer will point to 0x00000000004002f4 (<main+35>), the first instruction after function returns. To skip the assignment you need to make the saved instruction pointer point to 0x00000000004002fb (<main+42>).
Your calculation that this is 7 bytes is correct (0x4002fb - 0x4002fb = 7).
I used gdb to disassemble the application (disas main) and verified the calculation for my case as well. This value is best resolved manually by inspecting the disassembly.
Note that I used a Ubuntu 10.10 64-bit environment to test the following code.
#include <stdio.h>
void function(int a, int b, int c)
{
char buffer[5];
int *ret;
ret = (int *)(buffer + 24);
(*ret) += 7;
}
int main()
{
int x = 0;
function(1, 2, 3);
x = 1;
printf("x = %i \n", x);
return 0;
}
output
x = 0
This is really just altering the return address of function() rather than an actual buffer overflow. In an actual buffer overflow, you would be overflowing buffer[5] to overwrite the return address. However, most modern implementations use techniques such as stack canaries to protect against this.
What you're doing here doesn't seem to have much todo with a classic bufferoverflow attack. The whole idea of a bufferoverflow attack is to modify the return adress of 'function'. Disassembling your program will show you where the ret instruction (assuming x86) takes its adress from. This is what you need to modify to point at main+42.
I assume you want to explicitly provoke the bufferoverflow here, normally you'd need to provoke it by manipulating the inputs of 'function'.
By just declaring a buffer[5] you're moving the stackpointer in the wrong direction (verify this by looking at the generated assembly), the return adress is somewhere deeper inside in the stack (it was put there by the call instruction). In x86 stacks grow downwards, that is towards lower adresses.
I'd approach this by declaring an int* and moving it upward until I'm at the specified adress where the return adress has been pushed, then modify that value to point at main+42 and let function ret.
You can't do that this way.
Here's a classic bufferoverflow code sample. See what happens once you feed it with 5 and then 6 characters from your keyboard. If you go for more (16 chars should do) you'll overwrite base pointer, then function return address and you'll get segmentation fault. What you want to do is to figure out which 4 chars overwrite the return addr. and make the program execute your code. Google around linux stack, memory structure.
void ff(){
int a=0; char b[5];
scanf("%s",b);
printf("b:%x a:%x\n" ,b ,&a);
printf("b:'%s' a:%d\n" ,b ,a);
}
int main() {
ff();
return 0;
}

Resources