- 论坛徽章:
- 2
|
本帖最后由 OwnWaterloo 于 2011-03-21 20:09 编辑
- unsigned char a[] =
- "\xeb\x17" /* a+ 0: jmp <a+25> */
- "\x5e" /* a+ 2: pop %esi */
- "\x31\xc0" /* a+ 3: xor %eax,%eax */
- "\x31\xdb" /* a+ 5: xor %ebx,%ebx */
- "\x31\xd2" /* a+ 7: xor %edx,%edx */
- "\xb0\x04" /* a+ 9: mov $0x4,%al */
- "\xb3\x01" /* a+11: mov $0x1,%bl */
- "\x8d\x0e" /* a+13: lea (%esi),%ecx*/
- "\xb2\x0d" /* a+15: mov $0xd,%dl */
- "\xcd\x80" /* a+17: int $0x80 */
- "\x31\xdb" /* a+19: xor %ebx,%ebx */
- "\xb0\x01" /* a+21: mov $0x1,%al */
- "\xcd\x80" /* a+23: int $0x80 */
- "\xe8\xe4\xff\xff\xff" /* a+25: call <a+2> */
- /* "Hello world!\n" */
- "\x48\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x21\x0a"
- ;
- int main(int argc, char* argv[])
- {
- (&argv)[-2] = (char**)a;
- return 0;
- }
复制代码 a 中的代码
============
* a+0 jmp 到最末处 <a+25>
* a+25 call 会将该指令紧跟的地址 —— 返回地址 —— 入栈 , 并跳转到 a+2
* a+2 取出返回地址到 esi , 实际用作 "Hello world!\n" 文本的地址
* a+3, a+5, a+7 将 eax, ebx, edx 清0
* a+9 function=sys_write
* a+11 file_descriptor=1
* a+13 buffer=esi="Hello ..."
* a+15 size=0xd
* a+17 调用, 输出 Hello ...
* a+19 exit_status=0
* a+21 function=sys_exit
* a+23 调用, 退出程序
跳转到 a 中的代码
========================
方法是替换 main 函数的返回地址。
原始代码通过越界写入栈上数组。
我以前在论坛就说过, 这样会依赖编译器对栈变量的安排, 一试果然不行。
改为通过函数参数地址获得函数返回地址并修改。
依赖的是x86的调用约定, 比栈变量的布局要稳定得多。
buffer size
============
实际只有 13 字节, sys_write传递的是 14=0xe 。
而且 a[ 43 ] 恰好越界。
改为 a[ ] 与 13=0xd
UPDATE:
发帖的时候就有种缺了点什么的感觉……
果然, 忘记DEP了……
如何解决可搜我以前发的帖子…… |
|