Note: The uninterrupted disassembly is at the bottom
Hey, I'm looking at the the assembly and I'm trying to reverse engineer the function
Here, it seems like we are saving the previous rbp
. Though, it seems like there is no new value for rbp
0x004010b0 push rbp
We are clearing the xmm0
registers
0x004010b1 pxor xmm0, xmm0
Moving 0x40202c
into rdi
for the call fgets
. This would be the first argument. If I were to view the address at 0x40402c
, I would see the string Input
0x004010b5 lea rdi, str.Input: ; 0x40202c ; const char *s
Making room for local variables, but it seems odd to be doing it after the lea
and pxor
. So the previous stack frame never de-alloacted so we just increased it by much larger
0x004010bc sub rsp, 0x50
Moving the xmm0
onto the top of stack. I don't think I've ever seen an xmmword
before. I also imagine this is a local variable.
0x004010c0 movaps xmmword [rsp], xmm0
Ah, here's the rest of prologue! We are setting the value of rbp
to rsp
so the stack frame is 0
0x004010c4 mov rbp, rsp
Creating local variables!
0x004010c7 movaps xmmword [rsp + 0x10], xmm0
0x004010cc movaps xmmword [rsp + 0x20], xmm0
0x004010d1 movaps xmmword [rsp + 0x20], xmm0
Assigning a loval variable 0
. Because it is a byte, it is probably a char
0x004010d6 mov byte [rsp + 0x40], 0
We passed Input
into rdi
and called puts so we outputted Input
0x004010db call puts
Arguments are passed into rdi
, rsi
, and rdx
. So we have: fgets(rbp, 0x41, stdin)
.
It's also worth nothing that rbp
is probably the buffer and we passed 0x41
as the size which is a large buffer. The stack frame is 0
because we only recently moved the value of rsp
into rbp
. (i.e., rbp = rsp
).
And we did not not allocated space after the mov rbp, rsp
.
0x004010e0 mov rdx, qword [stdin] ; 0x404090 ; FILE *stream
0x004010e7 mov esi, 0x41
0x004010ec mov rdi, rbp
0x004010ef call fgets
rbp
was the buffer so we're moving the string into the first argument. The buffer might have been 65, but the char array could have terminated before that so the string length could have shorter.
0x004010f4 mov rdi, rbp
0x004010f7 call strlen
Pass the string itself, rbp
, and the length of the string, which was the return value of strlen
(and return values are placed in eax
) and pass it into the function
0x004010fc mov rdi, rbp
0x004010ff mov esi, eax
0x00401101 call fcn.0040152b
Clean up the stack and return 0!
0x00401106 add rsp, 0x50
0x0040110a xor eax, eax
0x0040110c pop rbp
0x0040110d ret
So, I imagine main
looks like
#include <stdio.h>
#include <string.h>
int main()
{
char str[65];
float local_var_1 = 0;
float local_var_2 = 0;
float local_var_3 = 0;
char rsp_40 = 0;
puts("Input");
fgets(str, 65, stdin);
int str_length = strlen(str);
some_fun(str, str_length);
return 0;
};
Is there anything wrong with this assessment?
The original assembly:
main:
0x004010b0 push rbp
0x004010b1 pxor xmm0, xmm0
0x004010b5 lea rdi, str.Input: ; 0x40202c ; const char *s
0x004010bc sub rsp, 0x50
0x004010c0 movaps xmmword [rsp], xmm0
0x004010c4 mov rbp, rsp
0x004010c7 movaps xmmword [rsp+0x10], xmm0
0x004010cc movaps xmmword [rsp+0x20], xmm0
0x004010d1 movaps xmmword [rsp+0x30], xmm0
0x004010d6 mov byte [rsp+0x40], 0
0x004010db call puts ; sym.imp.puts ; int puts(const char *s)
0x004010e0 mov rdx, qword [stdin] ; 0x404090 ; FILE *stream
0x004010e7 mov esi, 0x41 ; 'A' ; 65 ; int size
0x004010ec mov rdi, rbp ; char *s
0x004010ef call fgets ; sym.imp.fgets ; char *fgets(char *s, int size, FILE *stream)
0x004010f4 mov rdi, rbp ; const char *s
0x004010f7 call strlen ; sym.imp.strlen ; size_t strlen(const char *s)
0x004010fc mov rdi, rbp ; int64_t arg1
0x004010ff mov esi, eax ; uint64_t arg2
0x00401101 call fcn.0040152b
0x00401106 add rsp, 0x50
0x0040110a xor eax, eax
0x0040110c pop rbp
0x0040110d ret