2025 02 13
misc vn Figured that I should revisit my basics since I want to seriously revamp my binary exploitation skills. Now, I am not disregarding my malware analysis, reverse engineering, or other stuff. Actually, I think I will be having mathematics, astronomy, & philosophy take a back seat here, & let school teach that instead. To be honest, I was honestly hoping to clock in some mal-analysis but I am in the midst of backing up my mal-analysis setup since I nuked my preestablished snapshots. Nevertheless, with my wanting to return to CTFs, I must set priorities after all. When I get way more comfortable, then I can consider putting more effort into those.
And surprisingly, or unsurprisingly, I seem to have lost touch on much of the basics. I cannot believe I forgot procedure calls & stack frame operations. Now I am making my way back starting with reading Smashing The Stack For Fun & Profit by Aleph One, & it’s slowly coming back to me. It is quite a delightful read that I can recommend to anyone with enough technical experience. How much, I can’t really tell off the top of my head, sorry. I’d say understanding basic programming is all that is necessary, & from there one should be able to understand the depth with the assistance of Google. Nevertheless, I finally (& hopefully remains so) remember the direction that memory, stack, stack frames, & writes grow. Ignoring kernel magic & virtual memory, memory grows from 0 to the allocated size. There starts the .text section, the immutable portion which contains code. After follow the .data & .bss section in order, with the former containing static variables, meaning it’s immutable as well, & the latter with uninitialized variables, meaning it is writable. The .bss section is typically restricted to a certain size on runtime, but can be extended using the brk() function.
Now comes the stack, which starting from here is what messes me up to no small deed. The stack starts at the VERY END of the allocated memory. From there local stack frames are created to accomodate procedure calling conventions. So starting from the end, when a function is called, the function prologue will commence. In the function prologue, the machine will push the function parameters onto the stack. This can be however many, as we are sticking to 32-bit convention here. Then the program pushes the instruction pointer (eip/rip), which points to the instruction following the call in the to-be caller function, onto the stack as what is colloquially known as the return address. The stack looks like this now: {END OF MEM} [START OF STACK] … (arguments 1…n) (ret addr) [END OF STACK/stack ptr]…{START OF MEM}. Finally, the machine stores the updated stack pointer as the base pointer & further subtracts to accomodate local variables. The base pointer is the reference point to access local variables, since the stack pointer is volatile & not a confident source of reference. Now memory looks like this: {END OF MEM} [START OF STACK] … (arguments 1…n) (ret addr) (base ptr ^was originally stack ptr earlier^) [END OF STACK/stack ptr]…{START OF MEM}. And so repeats for further calls. Neat things to note from here is that parameters will always have a positive offset relative to a base pointer, making identifying them in disassembly easier. That goes without saying that the return address is, too, but with the silver lining that it starts right at the end of the base pointer, & is 4 bytes. Another thing to note, is that while the stack pointer is frequently changing with the construction & destruction of stack frames through various calls, the base of the stack does not change. It is essentially the ultimate boundary of the program alongside the bottom of memory at the other end. I suppose I could have just easily said that the base of the stack is always the end of memory, silly me. Reminder that although many similarities stick with other ISAs, this is strictly written according to 32-bit 8086. These are also what I explicitly remember & do not encompass all there is. Hope to finish this soon & start relearning stuff like pwntools & angr to proceed in bin exploit.
I was also able to practice & verify my skills in basic bin exploit in the meantime. Thankfully, I still remembered how to do basic classic buffer overflows, heap overflow, & some format string exploits. It goes without saying that I have only tested the bare minimum thus far. I also have yet to touch ROP, UAF, & ret2libc, which I can confidently say I remember, but not how much of. Also definitely a work in progress. With all these added to my plate, looks like I gotta lock in.
Nanami, uogh.