程序代写 An Excursion to gdb (1/3)

An Excursion to gdb (1/3)
• gdb is the universal debugger for Linux • Allows to step through a program and see
its current state
• Works both on source code and assembly

Copyright By PowCoder代写 加微信 powcoder

•~/.gdbinit allows to configure gdb
• Suggested configuration layout asm
layout regs
set disassembly-flavor intel
winheight REGS -2
winheight CMD -5
winheight ASM +5

An Excursion to gdb (2/3)
• General program navigation
• run start program execution
• b *0x8048000 / b main set breakpoint at address / function (alternatively: the instruction int3 in your code acts as breakpoint, too)
• info proc mappings
• Memory content analysis
single step instruction (follow call target) single step instruction (continues after call) print memory mappings
• x/x 0x8048000 • x/20x $esp
• x/s 0x80485f7
print one entry from 0x8048000 as hex
print 20 elements at the current stack pointer as hex print string at address 0x80485f7 (until \x00 is found)
• Setting registers/memory
•set $eip = 0x41414141 •set {int}0x8048000 = 0x90

An Excursion to gdb (3/3)
• Be careful: The way you see things in gdb differs from normal program execution:
Debuggers change the environment compared to a plain program execution
• Artifacts that have to be taken into account
• By default, gdb disables ASLR (address randomization; more on that later)
• gdb‘s environment variables changes the stack layout of a program
• gdb uses sockets, which changes socket / file descriptors number of program

Functions and the Stack

Stack (1/2)
• Stack: Memory in LIFO layout
• Local variables, function arguments, return values, …
• Two basic assembly primitives:
• push: Add data after top of stack (reduces rsp by number of
•pop: Remove data from top of stack into register (and increase
•rsp points to top of stack (i.e., to last element on stack)
pushing an element on the stack popping an element from the stack xx xx xx xx
zz RSP push zz

Stack (2/2)
•push/pop examples Assembly
SECTION .data
myvar dq 0xcafe;
SECTION .text
lea rax, [myvar]; rax contains address of myvar
push 0xbabe
push rax
pop rax
pop qword [myvar]
; push constant 0x000000000000BABE on stack ; push value in rax on stack
; pop into rax (rax := rax)
; pop into variable (myvar := 0xBABE)
; default push/pop size is 8B in x64, but 2B/4B can be specified push ax ; push value in ax on stack (ESP –= 2) push word 0xbabe ; push constant 0xBABE on stack (ESP -= 2)

Function Calls
• Invoke function: call fun
•call implicitly performs these two operations:
• Store return address on stack (next instr.)
– Register rip (x64) / eip (x86) stores address of address-wise subsequent instruction – push rip (implicitly rsp -= 8 in x64 or esp -= 4 in x86)
• Change control flow to callee – jmp fun
where fun is the address of the function’s code • Return to caller: ret ()
• Return value stored in rax(/eax)
•ret instruction implicitly performs these operations:
1. Optional: remove bytes from stack (cleanup; see later)
2. Restore return address from stack
– pop saved rip (implicitly rsp += 8 or esp += 4) 3. Change control flow back to caller

Linux Calling Convention in x64
• First 6 parameters passed via registers • rdi,rsi,rdx,rcx,r8,r9
• Additional parameters are passed on the stack • Return value in rax
• Who is responsible for saving registers?
• Non-volatile, callee-saved registers: rbp,rbx,r12-r15,rsp
– The called function (callee) has to save/restore registers before/after modification – Caller can rely on the fact that the callee does not alter the registers
• Volatile, caller-saved registers: all other registers
– Callee may alter registers at free will
– If still required, calling function needs to store registers before call and restore after call

Memory Layout: The Stack in x64 (1/2)
High address: 0xFF…FF
• Stack frame is function’s perspective on stack • Starts with rsp and local variables
• Ends at rbp (saved rip and parameters above)
• Stack frame is 16B aligned in x64, 8B aligned in x86
• Stack grows to lower addresses
•rsp: top of stack (stack pointer)
•rbp: start of current frame (base pointer)
8th parameter 7th parameter
return addr
local variable A
local variable B
Low address: 0x00…00
stack frame

Memory Layout: The Stack in x64 (2/2)
• Contents of specific addresses •rbp: caller’s RBP
•rbp+8: return address
• below rsp: ephemeral scratch space
• Stack’s base address
• Loader determines memory location of data
section of program (see PE/ELF header)
• Usually the stack is high up, but not adjacent to 0x07FF…FF
High address: 0xFF…FF
8th parameter 7th parameter
return addr
local variable
local variable
Low address: 0x00…00
stack frame

Memory Layout: The Stack in x64 (Example)
• Stack layout after function prologue of summing() C code
High address: 0xFF…FF
rbp of main rbp
Low address: 0x00…00
RDI=1, RSI=2, RDX=3,
RCX=4, R8=5, R9=6
uint64_t summing(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f,
stack frame
uint64_t g, uint64_t h) {
uint64_t x = a + b + c;
uint64_t y = d + e + f;
uint64_t z = g + h;
uint64_t s = x + y + z;
int main(int argc, char* argv[]) { summing(1, 2, 3, 4, 5, 6, 7, 8);
nxt:return 0;

Memory Layout: Setting Up the Stack
Save old rbp: push rbp
Establish frame: mov rbp, rsp
Reserve stack space for local vars
sub rsp,
Restore old frame (alternative: leave) mov rsp, rbp
Return to caller (ret)

Memory Layout: The Stack in x64 (Example)
void funA(int a, int b) {
uint64_t vA, vB;
vA = vA + vB;
void funB(int x, int y) {
uint64_t v1,v2,v3,v4;
funA(v1,v4+v3);
nB: v2=v1+v3+v4; }
int main(…) {
funB(1, 2);
nM: return 0; }
funB after prologue
addr: main.nM rbp of main
funA after prologue
RDI=1,RSI=2
addr: funB.nB rbp of funB
RDI=a,RSI=b

Memory Layout: Omit Frame Pointer
•rbp is not mandatory
• Addressing can be done relative to rsp •rsp-relative addressing is fairly common in x64
• Implementation
• gcc’s –fomit-frame-pointer (enabled in O1-3) does this • All stack addresses are relative to rsp
• rbp can be used as a general-purpose register
• Function prologue omits mov rbp, rsp
• Function epilogue omits pop rbp

Calling Conventions in x86 (obsolete)
• x86 (32-bit) has many different calling conventions
• Choice of the compiler
• Vary in how to pass parameters
– Parameters in registers vs. parameters in stack – Order of parameters in stack
– Set of registers of parameters
– Set of registers that need to be saved by callee
Calling Conv.
Params in Reg.
Params Order
Stack cleanup
Right-to-left
Right-to-left
Right-to-left
Right-to-left

Calling Conventions in x86 (obsolete)
• cdecl example C code
int addall(int a, int b, int c) {
Assembly (int main(), caller)
public main
push ebp
mov ebp, esp
push ecx
call addall
add esp, 0x0C
pop ecx
mov eax, 0
x += a + b + b + c + c + c;
int main() {
} return 0;
; store ebp
; store register ecx
; push 3 x 4 bytes
addall(1, 2, 3);
; call addall()
; clean up stack
; restore ecx
; return value

Memory Layout: The Stack in x86 (Example)
• Stack layout (cdecl) C code
Assembly code
01: push 0x3
02: call recurse
03: add esp,0x4
; in recurse
04: push ebp
05: mov ebp,esp
06: push ebx
07: mov ebx,[ebp+0x8]
08: cmp ebx,0x1
09: mov eax,0x1
10: jbe end_recurse
11: lea eax,[ebx-0x1]
12: push eax
13: call recurse
14: add esp,0x4
15: add eax,ebx
16: end_recurse:
17: pop ebx
18: leave
uint32_t recurse(uint32_t a) {
if (a <= 1) { } return a+recurse(a-1); int main(...) { recurse(3); Memory Layout: The Stack in x86 (Example) in recurse(3) in recurse(2) in recurse(1) 3 addr: main.fin ebp of funB addr: rec.fin ebp of rec3 addr: rec.fin ebp of rec2 System Calls System Calls using the Linux x64 ABI (1/2) • Calling convention like normal function calls • System call number placed in rax indicates the type of system call • Syscall parameters passed like in function calls but: 4th parameter is different (r10 instead of rcx), thus: rdi, rsi, rdx, r10, r8, r9 • When returning from system call, return value is stored in rax •syscall instruction initiates system call • Usually wrapped by system libraries (e.g., libc) • Could be used, in principle, by program itself (or by shellcode) System Calls using the Linux x64 ABI (2/2) • Example system calls: Assembly ; sys_exit(42) mov rax,60 ; system call number (sys_exit) mov rdi,42 ; system call return value syscall ; sys_write(stdout, buf, buflen) mov rax,1 ; system call number (1 = sys_write) mov rdi,1 ; arg1: fd (1 = stdout) mov rsi,buf ; arg2: buffer mov rdx,[buflen]; arg3: buflen • Good overview of system calls: • http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/ • https://github.com/torvalds/linux/blob/master/arch/x86/entry/syscalls/syscall_64.tbl What if... • ...an attacker could change the stored return address? caller return addr local variable local variable • Thinking exercise: a) Why could this happen? b) What can go wrong if it happens? stack frame 程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com