Mas0n
to be reverse engineer🐧
翻车鱼

虎符CTF2022

这次带着自己弱校队伍打了个第十,院校队真卷。

做了三题,大半夜做题脑子着实跟不上,shellcode被ror13迷惑了一万年……

解题过程写的比较笼统,逐渐变懒orz…

fpbe

bpf program

libbpf/libbpf.h at master · libbpf/libbpf (github.com)

/**
 * @brief **bpf_program__attach_uprobe()** attaches a BPF program
 * to the userspace function which is found by binary path and
 * offset. You can optionally specify a particular proccess to attach
 * to. You can also optionally attach the program to the function
 * exit instead of entry.
 *
 * @param prog BPF program to attach
 * @param retprobe Attach to function exit
 * @param pid Process ID to attach the uprobe to, 0 for self (own process),
 * -1 for all processes
 * @param binary_path Path to binary that contains the function symbol
 * @param func_offset Offset within the binary of the function symbol
 * @return Reference to the newly created BPF link; or NULL is returned on error,
 * error code is stored in errno
 */
LIBBPF_API struct bpf_link *
bpf_program__attach_uprobe(const struct bpf_program *prog, bool retprobe,
			   pid_t pid, const char *binary_path,
			   size_t func_offset);

使用bpftool dump出ir和流程图

> bpftool prog show
259: kprobe  name uprobe  tag d833ddf75360d0b4  gpl
        loaded_at 2022-03-19T11:15:32+0800  uid 0
        xlated 792B  jited 607B  memlock 4096B

> bpftool prog dump xlated id 259
···

> bpftool prog dump xlated id 259 visual &> output.out
> dot -Tpng output.out -o visual-graph.png

脚本生成伪代码

data = """   0: (79) r2 = *(u64 *)(r1 +104)
   1: (67) r2 <<= 32
   2: (77) r2 >>= 32
   ...
"""

av = []
for line in data.splitlines():
    if "goto" in line:
        t = line.split("goto")
        condtion, gotoLine = t[0].split("if")[1], f'goto _{str(int(line[:4]) + int(t[1].split("+")[1]) + 1)}'
        av.append("_"+line[:6].strip(" ") + f"if({condtion})" + '{' + gotoLine + ';}')
    else:
        av.append("_"+line[:6].strip(" ")+line[10:]+";")

print("\n".join(av))

重编译

#include <cstdint>
#include <cstdio>
#include <string>


typedef uint64_t u64;
typedef uint8_t u8;
typedef uint32_t u32;

int main() {
    u64 flag[4] = {0,1,2,3};
    u64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10;
    _0: r2 = *(u64 *)flag[2];
    _1: r2 <<= 32;
    _2: r2 >>= 32;
    _3: r3 = *(u64 *)flag[3];
    _4: r3 <<= 32;
    _5: r3 >>= 32;
    _6: r4 = r3;
    _7: r4 *= 28096;
    _8: r5 = r2;
    _9: r5 *= 64392;
    _10: r5 += r4;
    _11: r4 = *(u64 *)flag[1];
    _12: r4 <<= 32;
    _13: r4 >>= 32;
    _14: r0 = r4;
    _15: r0 *= 29179;
    _16: r5 += r0;
    _17: r1 = *(u64 *)flag[0];
    _18: r0 = 0;
    _19: *(u8 *)(r10 -8) = r0;
    _20: *(u64 *)(r10 -16) = r0;
    _21: *(u64 *)(r10 -24) = r0;
    _22: r1 <<= 32;
    _23: r1 >>= 32;
    _24: r0 = r1;
    _25: r0 *= 52366;
    _26: r5 += r0;
    _27: r6 = 1;
    _28: r0 = 0xbe18a1735995;
    _30:if( r5 != r0 ){goto _97;}
    _31: r5 = r3;
    _32: r5 *= 61887;
    _33: r0 = r2;
    _34: r0 *= 27365;
    _35: r0 += r5;
    _36: r5 = r4;
    _37: r5 *= 44499;
    _38: r0 += r5;
    _39: r5 = r1;
    _40: r5 *= 37508;
    _41: r0 += r5;
    _42: r5 = 0xa556e5540340;
    _44:if( r0 != r5 ){goto _97;}
    _45: r5 = r3;
    _46: r5 *= 56709;
    _47: r0 = r2;
    _48: r0 *= 32808;
    _49: r0 += r5;
    _50: r5 = r4;
    _51: r5 *= 25901;
    _52: r0 += r5;
    _53: r5 = r1;
    _54: r5 *= 59154;
    _55: r0 += r5;
    _56: r5 = 0xa6f374484da3;
    _58:if( r0 != r5 ){goto _97;}
    _59: r5 = r3;
    _60: r5 *= 33324;
    _61: r0 = r2;
    _62: r0 *= 51779;
    _63: r0 += r5;
    _64: r5 = r4;
    _65: r5 *= 31886;
    _66: r0 += r5;
    _67: r5 = r1;
    _68: r5 *= 62010;
    _69: r0 += r5;
    _70: r5 = 0xb99c485a7277;
    _72:if( r0 != r5 ){goto _97;}
    _73: *(u32 *)(r10 -12) = r1;
    _74: *(u32 *)(r10 -16) = r4;
    _75: *(u32 *)(r10 -20) = r2;
    _76: *(u32 *)(r10 -24) = r3;
    _77: r1 = 0xa7d73257b465443;
    _79: *(u64 *)(r10 -40) = r1;
    _80: r1 = 0x4648203a47414c46;
    _82: *(u64 *)(r10 -48) = r1;
    _83: r1 = 0x2052554f59202145;
    _85: *(u64 *)(r10 -56) = r1;
    _86: r1 = 0x4e4f44204c4c4557;
    _88: *(u64 *)(r10 -64) = r1;
    _89: r6 = 0;
    _90: *(u8 *)(r10 -32) = r6;
    _91: r1 = r10;
    _92: r1 += -64;
    _93: r3 = r10;
    _94: r3 += -24;
    _95: r2 = 33;
    _96:printf((char*)r1, r3);
    _97: r0 = r6;
    _98: exit;
    printf("\n");

    return 0;


}

hex-rays decompiler

https://cdn.shi1011.cn/2022/03/4d76631799d5e248f19c4c2a63db550f.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

线性方程组求解

from z3 import *

MEMORY = [BitVec(f"MEMORY{i}", 64) for i in range(4)]


sol = Solver()

sol.add(52366 * MEMORY[0] + 29179 * MEMORY[1] + 28096 * MEMORY[3] + 64392 * MEMORY[2] == 0xBE18A1735995)
sol.add(37508 * MEMORY[0] + 44499 * MEMORY[1] + 61887 * MEMORY[3] + 27365 * MEMORY[2] == 0xA556E5540340)
sol.add(59154 * MEMORY[0] + 25901 * MEMORY[1]+ 56709 * MEMORY[3] + 32808 * MEMORY[2] == 0xA6F374484DA3)
sol.add(62010 * MEMORY[0] + 31886 * MEMORY[1] + 33324 * MEMORY[3] + 51779 * MEMORY[2] == 0xB99C485A7277)

assert sol.check() == sat

mol = sol.model()
print(''.join([int.to_bytes(mol.eval(i).as_long(), length=8, byteorder="little")[:4].decode() for i in MEMORY][::-1]))

Contra 2048

表面上是个2048

用了webview 走的JavascriptInterface,gamemanager.js加了混淆

https://obfuscator.io

native加了微量ollvm bcf和fla,外加字符串混淆

frida hook dump出so

看到一堆anti-debug

https://cdn.shi1011.cn/2022/03/a11940d1fa8b856068f4ecf001fd007c.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

从pcap入手

分析消息的格式

struct msg
{
  _DWORD header;
  _DWORD type;
  _DWORD time;
  _DWORD hash;
  _DWORD flag;
  BYTE data[32];
};

重点关注类型type = 2

data组成如下

  • 4 bytes nums (0xdead + index)
  • 1 bytes input
  • zero padding
https://cdn.shi1011.cn/2022/03/e67fcf3a69516947298986132970996b.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

解析消息,获得密文

from construct import *
from Crypto.Cipher import AES

st = Struct(
    Const(b"HUFU"),
    "type" / Int32ul,
    "time" / Int32ul,
    "hash_0" / Hex(Int32ul),
    "flag" / Int32ul,
    "data" / Select(Bytes(32), Hex(Int64ul)),

)


peer0 = [[]] * 51

peer0[0] = [ # Packet 1
0x48, 0x55, 0x46, 0x55, 0x00, 0x00, 0x00, 0x00,
0x7a, 0x81, 0x13, 0x62, 0xcd, 0xd7, 0x40, 0x15,
0x20, 0x00, 0x00, 0x00, 0x62, 0x73, 0x6f, 0x54,
0x49, 0x4e, 0x58, 0x66, 0x50, 0x66, 0x58, 0x5a,
0x70, 0x51, 0x5a, 0x72, 0x65, 0x41, 0x4d, 0x75,
0x77, 0x73, 0x61, 0x56, 0x50, 0x75, 0x65, 0x6f,
0x6e, 0x72, 0x73, 0x47 ]
# ···


arrs = [bytearray(i) for i in peer0]

valueArr = []

for i in range(len(arrs)):
    data = arrs[i]
    p = st.parse(data)
    print(f"{i}:", p)
    if p["data"][0] == 0xff:
        ctx = AES.new(key=b"KZoLJZlLkRlMOtuD", mode=AES.MODE_ECB)
        value = p["data"][1:17]
        dec = ctx.decrypt(value)
        if dec[1] == 0xde:
            valueArr.append(dec)
        print("aesdec", dec.hex(), value.hex())


print(([i[4] for i in valueArr]))

gamemanager.js能看到首先对输入xtea,而后变表base64传入native调用check

https://cdn.shi1011.cn/2022/03/8f911c9b004ce0bdfc2465a031223426.jpg?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

相同check首先base64解码,而后魔改sbox aes加密

https://cdn.shi1011.cn/2022/03/941afbdc2266a6d1e2386b89179cc15e.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

找到aes key和xtea key逆过程解密

#include <cstdint>
#include <cstdio>
#include <string>

#define AES_BLOCK_SIZE      16
#define AES_ROUNDS          10  // 12, 14
#define AES_ROUND_KEY_SIZE  176 // AES-128 has 10 rounds, and there is a AddRoundKey before first round. (10+1)x16=176.

/*
 * round constants
 */
static uint8_t RC[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};

/*
 * Sbox
 */
static uint8_t SBOX[256] = {
        0xFC, 0xA1, 0xC1, 0x37, 0x3B, 0x43, 0x15, 0xDE, 0x7E, 0x24, 0x22, 0xEA, 0x62, 0xC2, 0x9F, 0x8F,
        0xA0, 0x3D, 0xF0, 0x05, 0xA9, 0x7B, 0x74, 0x50, 0xB9, 0x71, 0x58, 0x0F, 0xE1, 0x21, 0xB0, 0x85,
        0x25, 0x8D, 0x6A, 0x97, 0x91, 0x3F, 0xAD, 0x6D, 0xB7, 0xB4, 0xD0, 0x2C, 0x0C, 0x56, 0x7A, 0xAB,
        0x0A, 0x5B, 0x83, 0xC5, 0xD6, 0x52, 0xB6, 0x88, 0xC0, 0xC4, 0x5F, 0x92, 0xBC, 0xE2, 0x1A, 0x4D,
        0x76, 0x1F, 0x89, 0x1C, 0x23, 0xDF, 0xCA, 0x60, 0xE0, 0x17, 0x36, 0x75, 0xA7, 0x9E, 0x14, 0x5A,
        0x02, 0x46, 0x4A, 0x11, 0x2F, 0x8B, 0xF4, 0x33, 0xF2, 0x6E, 0x72, 0xA5, 0xC7, 0xE3, 0xDA, 0x38,
        0x53, 0x9B, 0x87, 0x09, 0x01, 0x4B, 0xA4, 0x42, 0x2E, 0xE7, 0x3A, 0x84, 0x12, 0x7F, 0x07, 0xBE,
        0xC8, 0xC9, 0x13, 0x47, 0xFE, 0xD1, 0xAC, 0xF6, 0xF1, 0xA8, 0x96, 0xB2, 0xC6, 0x18, 0xFB, 0xD4,
        0x82, 0x16, 0x73, 0x64, 0x5E, 0x7D, 0xEF, 0x0E, 0xAE, 0xA2, 0x0B, 0x30, 0xF7, 0xDD, 0xA6, 0x29,
        0x6C, 0xDC, 0x98, 0xFA, 0xBD, 0x67, 0xD5, 0xD8, 0xAF, 0x51, 0xE4, 0xBF, 0x65, 0x1D, 0xF8, 0xCE,
        0x9C, 0x26, 0xF3, 0x2A, 0x9A, 0x45, 0x08, 0x5C, 0x57, 0x06, 0x54, 0x2B, 0x41, 0x70, 0xB1, 0x63,
        0x66, 0x3C, 0x44, 0x10, 0x31, 0x19, 0x86, 0x61, 0x6B, 0xD7, 0x79, 0xCB, 0x81, 0x69, 0x0D, 0xD2,
        0xFF, 0x2D, 0x40, 0x03, 0x90, 0x9D, 0xE9, 0x4C, 0xCD, 0x00, 0xE5, 0x80, 0xDB, 0xBA, 0xCF, 0x48,
        0xD9, 0x3E, 0xFD, 0x4F, 0xEE, 0x8E, 0x4E, 0x77, 0xA3, 0xB5, 0x5D, 0x32, 0xE6, 0x68, 0x27, 0xAA,
        0xE8, 0x55, 0xF5, 0xCC, 0x78, 0x6F, 0xD3, 0x93, 0x7C, 0x28, 0x99, 0x34, 0xB3, 0x04, 0x95, 0x49,
        0xED, 0x8A, 0xF9, 0x1E, 0xB8, 0xC3, 0x8C, 0x59, 0xEB, 0xEC, 0x35, 0x39, 0xBB, 0x1B, 0x94, 0x20};

/*
 * Inverse Sboxs
 */
static uint8_t INV_SBOX[256] = {
        0xc9, 0x64, 0x50, 0xc3, 0xed, 0x13, 0xa9, 0x6e, 0xa6, 0x63, 0x30, 0x8a, 0x2c, 0xbe, 0x87, 0x1b,
        0xb3, 0x53, 0x6c, 0x72, 0x4e, 0x06, 0x81, 0x49, 0x7d, 0xb5, 0x3e, 0xfd, 0x43, 0x9d, 0xf3, 0x41,
        0xff, 0x1d, 0x0a, 0x44, 0x09, 0x20, 0xa1, 0xde, 0xe9, 0x8f, 0xa3, 0xab, 0x2b, 0xc1, 0x68, 0x54,
        0x8b, 0xb4, 0xdb, 0x57, 0xeb, 0xfa, 0x4a, 0x03, 0x5f, 0xfb, 0x6a, 0x04, 0xb1, 0x11, 0xd1, 0x25,
        0xc2, 0xac, 0x67, 0x05, 0xb2, 0xa5, 0x51, 0x73, 0xcf, 0xef, 0x52, 0x65, 0xc7, 0x3f, 0xd6, 0xd3,
        0x17, 0x99, 0x35, 0x60, 0xaa, 0xe1, 0x2d, 0xa8, 0x1a, 0xf7, 0x4f, 0x31, 0xa7, 0xda, 0x84, 0x3a,
        0x47, 0xb7, 0x0c, 0xaf, 0x83, 0x9c, 0xb0, 0x95, 0xdd, 0xbd, 0x22, 0xb8, 0x90, 0x27, 0x59, 0xe5,
        0xad, 0x19, 0x5a, 0x82, 0x16, 0x4b, 0x40, 0xd7, 0xe4, 0xba, 0x2e, 0x15, 0xe8, 0x85, 0x08, 0x6d,
        0xcb, 0xbc, 0x80, 0x32, 0x6b, 0x1f, 0xb6, 0x62, 0x37, 0x42, 0xf1, 0x55, 0xf6, 0x21, 0xd5, 0x0f,
        0xc4, 0x24, 0x3b, 0xe7, 0xfe, 0xee, 0x7a, 0x23, 0x92, 0xea, 0xa4, 0x61, 0xa0, 0xc5, 0x4d, 0x0e,
        0x10, 0x01, 0x89, 0xd8, 0x66, 0x5b, 0x8e, 0x4c, 0x79, 0x14, 0xdf, 0x2f, 0x76, 0x26, 0x88, 0x98,
        0x1e, 0xae, 0x7b, 0xec, 0x29, 0xd9, 0x36, 0x28, 0xf4, 0x18, 0xcd, 0xfc, 0x3c, 0x94, 0x6f, 0x9b,
        0x38, 0x02, 0x0d, 0xf5, 0x39, 0x33, 0x7c, 0x5c, 0x70, 0x71, 0x46, 0xbb, 0xe3, 0xc8, 0x9f, 0xce,
        0x2a, 0x75, 0xbf, 0xe6, 0x7f, 0x96, 0x34, 0xb9, 0x97, 0xd0, 0x5e, 0xcc, 0x91, 0x8d, 0x07, 0x45,
        0x48, 0x1c, 0x3d, 0x5d, 0x9a, 0xca, 0xdc, 0x69, 0xe0, 0xc6, 0x0b, 0xf8, 0xf9, 0xf0, 0xd4, 0x86,
        0x12, 0x78, 0x58, 0xa2, 0x56, 0xe2, 0x77, 0x8c, 0x9e, 0xf2, 0x93, 0x7e, 0x00, 0xd2, 0x74, 0xc0,
};

// ......

void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    unsigned int i;
    uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds;
    for (i=0; i < num_rounds; i++) {
        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
        sum -= delta;
        v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
    }
    v[0]=v0; v[1]=v1;
}

int main() {

    uint8_t roundkeys[AES_ROUND_KEY_SIZE];
    uint8_t key[16] = {72, 101, 108, 108, 111, 32, 102, 114, 111, 109, 32, 50, 48, 52, 56, 33};
    uint8_t data[48] = {174, 171, 207, 246, 74, 249, 129, 3, 174, 132, 149, 48, 57, 153, 218, 1, 53, 119, 54, 231, 124, 65, 77, 67, 239, 176, 170, 155, 1, 39, 33, 156, 2, 225, 14, 103, 194, 189, 254, 194, 163, 151, 234, 239, 101, 237, 139, 65};
    uint8_t out[48] = {0};
    aes_key_schedule_128(key, roundkeys);

    for (int i = 0; i < 3; ++i) {
        aes_decrypt_128(roundkeys, data+16*i, out+16*i);
    }
    
    
    uint32_t const k[4] = {745567528,745567520,2003788832,1679830126};
    for (int i = 0; i < 6; ++i) {
        uint32_t v[2] = {((uint32_t *) out)[i * 2], ((uint32_t *) out)[i * 2 + 1]};
        decipher(32, v, k);
        printf("0x%08x, 0x%08x, ", v[0], v[1]);
    }
    
    return 0;
}

the_shellcode

themida强壳,脱壳后分析(过程略)

注:脚本小子福利:https://github.com/ergrelet/unlicense

对shellcode base64解码后rol 3、xxtea后check

https://cdn.shi1011.cn/2022/03/1d2ad986db67967ed554fcbc03f1fa93.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

xxtea魔改了MX: z>>6

#include <cstdint>
#include <cstdio>
#include <string>


#define DELTA 0x9e3779b9
#define MX (((z>>6^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))

void btea(uint32_t *v, int n, uint32_t const key[4])
{
    uint32_t y, z, sum;
    unsigned p, rounds, e;
    if (n > 1)            /* Coding Part */
    {
        rounds = 6 + 52/n;
        sum = 0;
        z = v[n-1];
        do
        {
            sum += DELTA;
            e = (sum >> 2) & 3;
            for (p=0; p<n-1; p++)
            {
                y = v[p+1];
                uint32_t tmp = MX;
                v[p] += tmp;
                z = v[p];
            }
            y = v[0];
            z = v[n-1] += MX;
        }
        while (--rounds);
    }
    else if (n < -1)      /* Decoding Part */
    {
        n = -n;
        rounds = 6 + 52/n;
        sum = rounds*DELTA;
        y = v[0];
        do
        {
            e = (sum >> 2) & 3;
            for (p=n-1; p>0; p--)
            {
                z = v[p-1];
                v[p] -= MX;
                y = v[p];
            }
            z = v[n-1];
            y = v[0] -= MX;
            sum -= DELTA;
        }
        while (--rounds);
    }
}

int main() {
    uint32_t const k1[4] = {'t', 'o', 'r', 'a'};

    uint32_t vs[66] = {
            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,
    };


    btea(vs, -66, k1);
    for (int i = 0; i < 33; ++i) {
        printf("0x%08x, 0x%08x, ", vs[i*2+0], vs[i*2+1]);
    }
    return 0;
}

rol逆

def ROR(data, shift, size=32):
       shift %= size
       body = data >> shift
       remains = (data << (size - shift)) - (body << size)
       return (body + remains)


value = [0x6243e703, 0x993831bb, 0x925c2396, 0x60925c81, 0x5ca0925c, 0xbd784193, 0xff993152, 0xe1650699, 0x6110e30b, 0x687e0e01,
0x8717c718, 0x925cba92, 0xe1125c80, 0x025c1618, 0x78062cc3, 0x0000f524, 0x82161800, 0x5cc0425c, 0xd61801c2, 0x7800cf1c,
0x00004d24, 0xa15c4a00, 0x9997185c, 0x650699ff, 0x18687e0e, 0xab26d1c7, 0x21e318a7, 0x21e3d920, 0x99ceab60, 0x1c4e99ff,
0xb5788216, 0x7e0e5020, 0x0ac71868, 0xab70cf1c, 0x687e0e8f, 0x99ff99ba, 0x21a25c4e, 0xb57892e1, 0x3bc570e0, 0xbf333333,
0x5cd78e5f, 0xf8470e16, 0x206c1618, 0xd2c65904, 0x5020b578, 0x7e0e1e59, 0x0ac71868, 0xab70cf1c, 0x687e0ea6, 0xa321e1d9,
0x9b2943b0, 0x265c0000, 0x007b7343, 0x5c82a200, 0xff4221e2, 0x43a05f9e, 0x00009b29, 0xcb43265c, 0xa2009b2b, 0x21e25c82,
0xc29eff42, 0xc2c2c2c2, 0xc2c2c2c2, 0xfac21e0b, 0x4f905cd2, 0xffffff58,]

data = struct.pack("<66L", *value)

data = bytearray([ROR(i, 3, 8) for i in data])

shellcode = base64.b64encode(data).decode()
print(shellcode)

check flag用了ror13 hash

def ror13(target):
    # return ((target << 0x13) & 0xfff80000) | ((target >> 0xd) & 0x07ffff)
    return ((target << 0x13) & 0xffffffff) | ((target >> 0xd) & 0x07ffff)


def calc(s):
    target = 0
    for c in s:
        target = ror13(target)
        target += c
    return target

带壳调试,反壳带的anti-debug后,拿到需要的参数,简单逆过程

import hashlib

msd = b'LoadLibraryExA'
data = bytearray(b''.fromhex("69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E"))
for i in range(14):
    data[i] += msd[i] % 5

base = b"YPxoTHcmBzPSZItSMItSDItSFItyKA+3SiYz/zPArDxhfAIsIMHPDQP44vBSV4tSEItCPAPCi0B4hcAPhL4AAAADwlCLSBiLWCAD2oP5AA+EqQAAAEmLNIsD8jP/M8Cswc8NA/g6xHX0A3wkBDt8JAx12TP/M8mDwlAPtgQKwc8NA/hBg/kOdfHBzw1XM/8zyYtUJDxSD7YcDrhnZmZm9+vR+ovCwegfA8KNBIAr2FoPtgQKK8PBzw0D+EGD+Q511MHPDTs8JHQWaCVzAACLxGhubwAAVFCLXCRI/9PrFGglcwAAi8RoeWVzAFRQi1wkSP/TWFhYWFhYWFhYYcNYX1qLEukL////"
base += data
print(hashlib.md5(base).hexdigest())

本文链接:https://blog.shi1011.cn/ctf/2259
本文采用 CC BY-NC-SA 4.0 Unported 协议进行许可

Mas0n

文章作者

发表回复

textsms
account_circle
email

翻车鱼

虎符CTF2022
这次带着自己弱校队伍打了个第十,院校队真卷。 做了三题,大半夜做题脑子着实跟不上,shellcode被ror13迷惑了一万年…… 解题过程写的比较笼统,逐渐变懒orz... fpbe bpf prog…
扫描二维码继续阅读
2022-03-21