hitcon2023逆向 The Blade WP

hitcon2023逆向 The Blade WP

png

运行所给的程序 socket通信相关

在这里插入图片描述

在这里插入图片描述

由题目描述A Rust tool for executing shellcode in a seccomp environment.

字符串查找定位 发现其中verify方法可疑

在这里插入图片描述

发现隐藏了一个命令flag 是以添加命令行参数的方式输入flag 调试得知输入flag长度为64位

在这里插入图片描述

F7进入verify 发现加密逻辑 简单来讲 是一个大的256次while循环 里面有好几个通过固定的表对输入进行打乱,然后一个有点复杂的加密逻辑,有取余有除有异或,于是就有个骚操作的想法,既然逆向加密算法比较复杂,就找出00-ff的映射就行了 因为是按位加密的伐然后前面的几次打乱顺序由于是固定的表所以可以看成一次打乱顺序 找出索引交换的顺序即可

do
  {
    ++v8;
    memcpy(dest, "/", 0x200uLL);
    v9 = 64LL;
    v10 = &dest[1];
    do
    {
      v11 = *(v10 - 1);
      if ( v11 >= 64
        || (v12 = flagg[v9 - 1], flagg[v9 - 1] = flagg[v11], flagg[v11] = v12, v13 = *v10, (unsigned __int64)*v10 > 0x3F) )
      {
LABEL_53:
        core::panicking::panic_bounds_check::h7d0e683548e4cb10();
      }
      v14 = flagg[v9 - 2];
      flagg[v9 - 2] = flagg[v13];
      flagg[v13] = v14;
      v10 += 2;
      v9 -= 2LL;
    }
    while ( v9 );
    memcpy(dest, &unk_55C3745E9D20, 0x200uLL);
    v15 = 64LL;
    v16 = &dest[1];
    do
    {
      v17 = *(v16 - 1);
      if ( v17 > 63 )
        goto LABEL_53;
      v18 = flagg[v15 - 1];
      flagg[v15 - 1] = flagg[v17];
      flagg[v17] = v18;
      v19 = *v16;
      if ( (unsigned __int64)*v16 > 63 )
        goto LABEL_53;
      v20 = flagg[v15 - 2];
      flagg[v15 - 2] = flagg[v19];
      flagg[v19] = v20;
      v16 += 2;
      v15 -= 2LL;
    }
    while ( v15 );
    memcpy(dest, &unk_55C3745E9F20, 0x200uLL);
    v21 = 64LL;
    v22 = &dest[1];
    do
    {
      v23 = *(v22 - 1);
      if ( v23 > 0x3F )
        goto LABEL_53;
      v24 = flagg[v21 - 1];
      flagg[v21 - 1] = flagg[v23];
      flagg[v23] = v24;
      v25 = *v22;
      if ( (unsigned __int64)*v22 > 0x3F )
        goto LABEL_53;
      v26 = flagg[v21 - 2];
      flagg[v21 - 2] = flagg[v25];
      flagg[v25] = v26;
      v22 += 2;
      v21 -= 2LL;
    }
    while ( v21 );
    memcpy(dest, &unk_55C3745EA120, 0x200uLL);
    v27 = 64LL;
    v28 = &dest[1];
    do
    {
      v29 = *(v28 - 1);
      if ( v29 > 0x3F )
        goto LABEL_53;
      v30 = flagg[v27 - 1];
      flagg[v27 - 1] = flagg[v29];
      flagg[v29] = v30;
      v31 = *v28;
      if ( (unsigned __int64)*v28 > 0x3F )
        goto LABEL_53;
      v32 = flagg[v27 - 2];
      flagg[v27 - 2] = flagg[v31];
      flagg[v31] = v32;
      v28 += 2;
      v27 -= 2LL;
    }
    while ( v27 );
    memcpy(dest, &unk_55C3745EA320, 0x200uLL);
    v33 = 64LL;
    v34 = &dest[1];
    do
    {
      v35 = *(v34 - 1);
      if ( v35 > 0x3F )
        goto LABEL_53;
      v36 = flagg[v33 - 1];
      flagg[v33 - 1] = flagg[v35];
      flagg[v35] = v36;
      v37 = *v34;
      if ( (unsigned __int64)*v34 > 0x3F )
        goto LABEL_53;
      v38 = flagg[v33 - 2];
      flagg[v33 - 2] = flagg[v37];
      flagg[v37] = v38;
      v34 += 2;
      v33 -= 2LL;
    }
    while ( v33 );
    memcpy(dest, &unk_55C3745EA520, 0x200uLL);
    v39 = 64LL;
    v40 = &dest[1];
    do
    {
      v41 = *(v40 - 1);
      if ( v41 > 0x3F )
        goto LABEL_53;
      v42 = flagg[v39 - 1];
      flagg[v39 - 1] = flagg[v41];
      flagg[v41] = v42;
      v43 = *v40;
      if ( (unsigned __int64)*v40 > 0x3F )
        goto LABEL_53;
      v44 = flagg[v39 - 2];
      flagg[v39 - 2] = flagg[v43];
      flagg[v43] = v44;
      v40 += 2;
      v39 -= 2LL;
    }
    while ( v39 );
    memcpy(dest, &unk_55C3745EA720, 0x200uLL);
    v45 = 64LL;
    v46 = &dest[1];
    do
    {
      v47 = *(v46 - 1);
      if ( v47 > 0x3F )
        goto LABEL_53;
      v48 = flagg[v45 - 1];
      flagg[v45 - 1] = flagg[v47];
      flagg[v47] = v48;
      v49 = *v46;
      if ( (unsigned __int64)*v46 > 0x3F )
        goto LABEL_53;
      v50 = flagg[v45 - 2];
      flagg[v45 - 2] = flagg[v49];
      flagg[v49] = v50;
      v46 += 2;
      v45 -= 2LL;
    }
    while ( v45 );
    memcpy(dest, &unk_55C3745EA920, 0x200uLL);
    v52 = 64LL;
    v53 = &dest[1];
    do
    {
      v54 = *(v53 - 1);
      if ( v54 > 0x3F )
        goto LABEL_53;
      v55 = flagg[v52 - 1];
      flagg[v52 - 1] = flagg[v54];
      flagg[v54] = v55;
      v56 = *v53;
      if ( (unsigned __int64)*v53 > 0x3F )
        goto LABEL_53;
      v57 = flagg[v52 - 2];
      flagg[v52 - 2] = flagg[v56];
      flagg[v56] = v57;
      v53 += 2;
      v52 -= 2LL;
    }
    while ( v52 );
    v58 = 0LL;
    do
    {
      v59 = (unsigned __int8)flagg[v58] + 1;
      LOWORD(v51) = 1;
      LOWORD(v52) = 257;
      v60 = 0;
      do
      {
        v62 = v52;
        LOWORD(v52) = (unsigned __int16)v52 / (unsigned __int16)v59;
        v61 = v62 % (unsigned __int16)v59;
        v63 = v51;
        v51 = v60 - v51 * v52;
        LODWORD(v52) = v59;
        v59 = (unsigned __int16)(v62 % (unsigned __int16)v59);
        v60 = v63;
      }
      while ( v61 );
      v64 = 0;
      if ( (__int16)v63 > 0 )
        v64 = v63;
      flagg[v58] = ((unsigned __int16)(v64 + ((__int16)v63 >> 15) - v63) / 0x101u
                  + v63
                  + ((unsigned __int16)v63 >> 15)
                  + 113) ^ 0x89;
      v52 = v58 + 1;
      v58 = v52;
    }
    while ( v52 != 64 );
  }
  while ( v8 != 256 );//提取出的总的加密

在这里插入图片描述

不出意外的话64位比较数据是cmp=[0xA7, 0x51, 0x68, 0x52, 0x85, 0x27, 0xFF, 0x31, 0x88, 0x87, 0xD2, 0xC7, 0xD3, 0x23, 0x3F, 0x52, 0x55, 0x10, 0x1F, 0xAF, 0x27, 0xF0, 0x94, 0x5C, 0xCD, 0x3F, 0x7A, 0x79, 0x9F, 0x2F, 0xF0, 0xE7, 0x45, 0xF0, 0x86, 0x3C, 0xF9, 0xB0, 0xEA, 0x6D, 0x90, 0x42, 0xF7, 0x91, 0xED, 0x3A, 0x9A, 0x7C, 0x01, 0x6B, 0x84, 0xDC, 0x6C, 0xC8, 0x43, 0x07, 0x5C, 0x08, 0xF7, 0xDF, 0xEB, 0xE3, 0xAE, 0xA4] (也就是这64位的4个xmmword)

测试用数据0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{}

原顺序0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{}
断点得打乱后的顺序HfVl{qPcCYNMoRi6D7Jr}espOL3FhwdWAtTGZba4Ugjvnx1QkKE2IS9yuz5BX08m

字符的加密逻辑:

do
    {
      v59 = (unsigned __int8)flagg[v58] + 1;
      LOWORD(v51) = 1;
      LOWORD(v52) = 257;
      v60 = 0;
      do
      {
        v62 = v52;
        LOWORD(v52) = (unsigned __int16)v52 / (unsigned __int16)v59;
        v61 = v62 % (unsigned __int16)v59;
        v63 = v51;
        v51 = v60 - v51 * v52;
        LODWORD(v52) = v59;
        v59 = (unsigned __int16)(v62 % (unsigned __int16)v59);
        v60 = v63;
      }
      while ( v61 );
      v64 = 0;
      if ( (__int16)v63 > 0 )
        v64 = v63;
      flagg[v58] = ((unsigned __int16)(v64 + ((__int16)v63 >> 15) - v63) / 0x101u
                  + v63
                  + ((unsigned __int16)v63 >> 15)
                  + 113) ^ 0x89;
      v52 = v58 + 1;
      v58 = v52;
    }
    while ( v52 != 64 );

得解密脚本

def decrypt(data: list, table: dict):
    tmp=[]
    for i in data:
        tmp.append(table[i])
    return tmp

def reverse_order(data:list, table: list):
    tmp = []
    for i in range(64):
        tmp.append(data[table[i]])
    return tmp

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

#get order table
source = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{}'
replaced = 'HfVl{qPcCYNMoRi6D7Jr}espOL3FhwdWAtTGZba4Ugjvnx1QkKE2IS9yuz5BX08m'
revsere_table = [] #index是source在replace中的下标
for i in source:
    revsere_table.append(replaced.find(i))

tmp = [0x52, 0xCB, 0x15, 0x10, 0x7E, 0xD3, 0x78, 0x26, 0xC2, 0x14, 0x09, 0x50, 0x55, 0xFA, 0xEE, 0xC3, 0x0A, 0x97, 0xB9, 0x38, 0x12, 0x3D, 0x0E, 0xE9, 0xBE, 0xF6, 0x2B, 0x66, 0x67, 0xA8, 0x87, 0xAE, 0x1D, 0x53, 0x62, 0xEC, 0xFC, 0x5C, 0x88, 0x68, 0x23, 0x5B, 0x36, 0x13, 0xFB, 0xD7, 0xCA, 0x7A, 0xBD, 0xD9, 0x69, 0x6A, 0xE4, 0x2A, 0x6C, 0x9D, 0x86, 0xE0, 0xA4, 0x01, 0xBA, 0x3B, 0x20, 0x92]
for i in range(256):
    tmp = decrypt(tmp, crypto_table)
    tmp = reverse_order(tmp, revsere_table)
print(''.join(chr(i) for i in tmp))
# 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{}
#(tmp的值就是测试用数据经历过完整的打乱顺序和加密后dump出的,并不是最终的cmp_data)

上面的脚本用于解密 排序+加密

但用这个脚本解密比较数据是乱码 说明要么是比较数据还有操作 要么是input还有操作

继续往后面看 比较逻辑

在这里插入图片描述

 like_i = 4LL;
  do
  {
    v77 = v84;                                  // 0xff
    if ( v84 < 205 )
      goto LABEL_74;
    *(_DWORD *)v78 = *(_DWORD *)((char *)dest + like_i);
    v79 = v82;
    v82[204] = input[like_i];
    if ( v77 < 224 )
      goto LABEL_74;
    v79[223] = v78[0];
    v79[205] = input[like_i + 1];
    if ( v77 == 224 )
      goto LABEL_74;
    v79[224] = v78[1];
    v79[206] = input[like_i + 2];
    if ( v77 < 226 )
      goto LABEL_74;
    v79[225] = v78[2];
    v79[207] = input[like_i + 3];
    if ( v77 == 226 )
      goto LABEL_74;
    v79[226] = v78[3];
    _$LT$$RF$std..net..tcp..TcpStream$u20$as$u20$std..io..Write$GT$::write::h0bbfc2d1fa700c7a();
    if ( v81[0] )
      goto LABEL_50;
    v81[0] = 0LL;
    v75 = std::io::default_read_exact::h61fb53e2a02eb302(&v85, v81, 8LL);
    if ( v75 )
      goto LABEL_55;
    if ( !v81[0] )
      goto LABEL_70;
    v80 = (unsigned __int64)(like_i + 1) <= 60;
    like_i += 4LL;
  }
  while ( v80 );

每次是赋值了input的4个字节 和比较数据的四个字节 但是不清楚跑哪里去了

而v79[204] v79[205] v79[206] v79[207] 是栈中固定的位置,为什么下标怎么奇怪呢?

通过查找交叉引用可以发现

在这里插入图片描述

v79是一开始255字节长的shellcode

在这里插入图片描述

IDA有些识别不太准确 在汇编中查看

.rodata:000055E808DA1B2B sub_55E808DA1B2B proc near              ; DATA XREF: seccomp_shell::shell::verify::h898bf5fa26dafbab+44D↑o
.rodata:000055E808DA1B2B push    rsp
.rodata:000055E808DA1B2C pop     rbp
.rodata:000055E808DA1B2D xor     esi, esi                        ; flags
.rodata:000055E808DA1B2F mov     rcx, 379F3A62B80657A1h
.rodata:000055E808DA1B39 mov     rdx, 37F7494DD66F358Eh
.rodata:000055E808DA1B43 xor     rcx, rdx
.rodata:000055E808DA1B46 push    rcx
.rodata:000055E808DA1B47 push    rsp
.rodata:000055E808DA1B48 pop     rdi                             ; filename
.rodata:000055E808DA1B49 push    2
.rodata:000055E808DA1B4B pop     rax
.rodata:000055E808DA1B4C cdq                                     ; mode
.rodata:000055E808DA1B4D syscall                                 ; LINUX - sys_open
.rodata:000055E808DA1B4F xchg    rax, rdi                        ; fd
.rodata:000055E808DA1B51 xor     eax, eax
.rodata:000055E808DA1B53 push    rax
.rodata:000055E808DA1B54 push    rsp
.rodata:000055E808DA1B55 pop     rsi                             ; buf
.rodata:000055E808DA1B56 push    4
.rodata:000055E808DA1B58 pop     rdx                             ; count
.rodata:000055E808DA1B59 syscall                                 ; LINUX - sys_read
.rodata:000055E808DA1B5B pop     r12
.rodata:000055E808DA1B5D push    3
.rodata:000055E808DA1B5F pop     rax
.rodata:000055E808DA1B60 syscall                                 ; LINUX - sys_close
.rodata:000055E808DA1B62 xor     esi, esi                        ; flags
.rodata:000055E808DA1B64 mov     rcx, 0AAC06463C36F3B3Bh
.rodata:000055E808DA1B6E mov     rdx, 0AAC06463C30B4C48h
.rodata:000055E808DA1B78 xor     rcx, rdx
.rodata:000055E808DA1B7B push    rcx
.rodata:000055E808DA1B7C mov     rcx, 7DA9F8D67582578Ch
.rodata:000055E808DA1B86 mov     rdx, 0EC888F916F632A3h
.rodata:000055E808DA1B90 xor     rcx, rdx
.rodata:000055E808DA1B93 push    rcx
.rodata:000055E808DA1B94 push    rsp
.rodata:000055E808DA1B95 pop     rdi                             ; filename
.rodata:000055E808DA1B96 push    2
.rodata:000055E808DA1B98 pop     rax
.rodata:000055E808DA1B99 cdq                                     ; mode
.rodata:000055E808DA1B9A syscall                                 ; LINUX - sys_open
.rodata:000055E808DA1B9C xchg    rax, rdi                        ; fd
.rodata:000055E808DA1B9E xor     eax, eax
.rodata:000055E808DA1BA0 push    rax
.rodata:000055E808DA1BA1 push    rsp
.rodata:000055E808DA1BA2 pop     rsi                             ; buf
.rodata:000055E808DA1BA3 push    4
.rodata:000055E808DA1BA5 pop     rdx                             ; count
.rodata:000055E808DA1BA6 syscall                                 ; LINUX - sys_read
.rodata:000055E808DA1BA8 pop     r13
.rodata:000055E808DA1BAA push    3
.rodata:000055E808DA1BAC pop     rax
.rodata:000055E808DA1BAD syscall                                 ; LINUX - sys_close
.rodata:000055E808DA1BAF xor     esi, esi                        ; flags
.rodata:000055E808DA1BB1 push    6Fh ; 'o'
.rodata:000055E808DA1BB3 mov     rcx, 77D9F62D0C06E559h
.rodata:000055E808DA1BBD mov     rdx, 5BC8C027A638176h
.rodata:000055E808DA1BC7 xor     rcx, rdx
.rodata:000055E808DA1BCA push    rcx
.rodata:000055E808DA1BCB push    rsp
.rodata:000055E808DA1BCC pop     rdi                             ; filename
.rodata:000055E808DA1BCD push    2
.rodata:000055E808DA1BCF pop     rax
.rodata:000055E808DA1BD0 cdq                                     ; mode
.rodata:000055E808DA1BD1 syscall                                 ; LINUX - sys_open
.rodata:000055E808DA1BD3 xchg    rax, rdi                        ; fd
.rodata:000055E808DA1BD5 xor     eax, eax
.rodata:000055E808DA1BD7 push    rax
.rodata:000055E808DA1BD8 push    rsp
.rodata:000055E808DA1BD9 pop     rsi                             ; buf
.rodata:000055E808DA1BDA push    4
.rodata:000055E808DA1BDC pop     rdx                             ; count
.rodata:000055E808DA1BDD syscall                                 ; LINUX - sys_read
.rodata:000055E808DA1BDF pop     rax
.rodata:000055E808DA1BE0 not     rax
.rodata:000055E808DA1BE3 shr     rax, 1Dh
.rodata:000055E808DA1BE7 cqo
.rodata:000055E808DA1BE9 push    29h ; ')'
.rodata:000055E808DA1BEB pop     rcx
.rodata:000055E808DA1BEC div     rcx
.rodata:000055E808DA1BEF xchg    rax, r14
.rodata:000055E808DA1BF1 push    3
.rodata:000055E808DA1BF3 pop     rax
.rodata:000055E808DA1BF4 syscall                                 ; LINUX - sys_close
.rodata:000055E808DA1BF6 mov     eax, 267814C2h
.rodata:000055E808DA1BFB add     eax, r12d
.rodata:000055E808DA1BFE xor     eax, r13d
.rodata:000055E808DA1C01 ror     eax, 0Bh
.rodata:000055E808DA1C04 not     eax
.rodata:000055E808DA1C06 xor     eax, r14d
.rodata:000055E808DA1C09 cmp     eax, 31FF2788h
.rodata:000055E808DA1C0E jnz     short loc_55E808DA1C15
.rodata:000055E808DA1C0E
.rodata:000055E808DA1C10 push    1
.rodata:000055E808DA1C12 pop     rax
.rodata:000055E808DA1C13 jmp     short loc_55E808DA1C18
.rodata:000055E808DA1C13
.rodata:000055E808DA1C15 ; ---------------------------------------------------------------------------
.rodata:000055E808DA1C15
.rodata:000055E808DA1C15 loc_55E808DA1C15:                       ; CODE XREF: sub_55E808DA1B2B+E3↑j
.rodata:000055E808DA1C15 xor     rax, rax
.rodata:000055E808DA1C15
.rodata:000055E808DA1C18
.rodata:000055E808DA1C18 loc_55E808DA1C18:                       ; CODE XREF: sub_55E808DA1B2B+E8↑j
.rodata:000055E808DA1C18 push    rax
.rodata:000055E808DA1C19 push    rbx
.rodata:000055E808DA1C1A pop     rdi                             ; fd
.rodata:000055E808DA1C1B push    rsp
.rodata:000055E808DA1C1C pop     rsi                             ; buf
.rodata:000055E808DA1C1D push    8
.rodata:000055E808DA1C1F pop     rdx                             ; count
.rodata:000055E808DA1C20 push    1
.rodata:000055E808DA1C22 pop     rax
.rodata:000055E808DA1C23 syscall                                 ; LINUX - sys_write
.rodata:000055E808DA1C25 push    rbp
.rodata:000055E808DA1C26 pop     rsp
.rodata:000055E808DA1C27 jmp     r15
.rodata:000055E808DA1C27
.rodata:000055E808DA1C27 sub_55E808DA1B2B endp
.rodata:000055E808DA1C27

发现之前赋值的input和比较数据都跑这里来了

在这里插入图片描述

add eax, r12d #首先将eax与r12d相加
xor eax, r13d #然后将eax与r13d进行异或运算
ror eax, 0Bh #接着将eax向右旋转11位
not eax#然后对eax求反
xor eax, r14d#再将eax与r14d进行异或运算

关键就是上面几条汇编指令了 对input还进行了操作

关键就是找到r12 r13 r14的值

但这个shellcode在程序中好像没有拿出来执行(也可能是因为我不会调)

而且这个程序好像就单纯的验证了服务器端和客服端的输入是否相同 有点闹麻

在这里插入图片描述

(有一个std::io::default_read_exact是从客服端接受,从IDA动态调试会卡住也能发现这一点)

分析shellcode可以得出r12 r13 r14是定值

分析方法:随便找一个简单的程序 用IDApatch成shellcode执行一下就行了

直接用lazyIDA paste data

在这里插入图片描述

在这里插入图片描述

可以发现r12 r13 r14的定值是多少 然后就直接写exp脚本解得flag就OK了

import numpy as np
def decrypt(data: list, table: dict):
    tmp=[]
    for i in data:
        tmp.append(table[i])
    return tmp

def reverse_order(data:list, table: list):
    tmp = []
    for i in range(64):
        tmp.append(data[table[i]])
    return tmp



# 定义一个函数,接受一个参数,返回解密后的值
def de_cmp(x):
    # 定义r12, r13, r14的值
    r12 = 0x0000000464C457F
    r13 = 0x0000000746F6F72
    r14 = 0x000000031F3831F
    # 将x转换为无符号32位整数
    x = np.uint32(x)
    # 将x与r14异或
    x = np.uint32(x ^ r14)
    # 将x取反
    x = np.uint32(~x)
    # 将x左旋11位
    x = np.uint32((x << 11) | (x >> (32 - 11)))
    # 将x与r13异或
    x = np.uint32(x ^ r13)
    # 将x减去r12
    x = np.uint32(x - r12)
    # 打印x的十六进制表示
    print(hex(x))
    # 将x转换为有符号32位整数
    x = np.int32(x)
    # 返回x的四个字节
    return [x & 0xff, (x & 0xff00) >> 8, (x & 0xff0000) >> 16, (x & 0xff000000) >> 24]
#get crypto table
s0_255 = [0xFB, 0x7B, 0x4E, 0xBB, 0x51, 0x15, 0x8D, 0xDB, 0xB0, 0xAC, 0xA5, 0x8E, 0xAA, 0xB2, 0x60, 0xEB, 0x63, 0x5C, 0xDE, 0x42, 0x2B, 0xC6, 0xA6, 0x35, 0x30, 0x43, 0xD6, 0x5F, 0xBD, 0x24, 0xB1, 0xE3, 0x8C, 0xA7, 0xD5, 0x2A, 0x7C, 0x6D, 0x8B, 0x17, 0x9D, 0x83, 0xFE, 0x69, 0x10, 0x59, 0xA9, 0x9E, 0x0F, 0x1C, 0x66, 0x97, 0x5B, 0x61, 0xED, 0xAD, 0xE0, 0xDA, 0x27, 0x06, 0x25, 0xDC, 0x5E, 0xE7,
        0x41, 0x32, 0xD2, 0xD9, 0x8F, 0xEE, 0xAF, 0x03, 0x93, 0x3A, 0x00, 0xA2, 0xE1, 0xB3, 0xEC, 0x81, 0x9F, 0xCA, 0x58, 0xB7, 0x79, 0xFD, 0x3B, 0xA0, 0x02, 0x0C, 0xCB, 0xA8, 0x80, 0xC0, 0x16, 0x4D, 0x2F, 0x75, 0x71, 0x0A, 0x04, 0x39, 0xFF, 0xC1, 0x9C, 0xAB, 0xEF, 0xA4, 0xD8, 0xE2, 0x14, 0xC2, 0x6C, 0x64, 0x1E, 0x6B, 0x7E, 0x99, 0x2E, 0x09, 0x0B, 0x86, 0x74, 0x6A, 0xC4, 0x2D, 0x4F, 0xF9,
        0xFA, 0x94, 0xB6, 0x1F, 0x89, 0x6F, 0x5D, 0xE8, 0xEA, 0xB5, 0x5A, 0x65, 0x88, 0xC5, 0x7F, 0x77, 0x11, 0xCF, 0xF1, 0x1B, 0x3F, 0xF4, 0x48, 0x47, 0x12, 0xE4, 0xBA, 0xDF, 0xE9, 0x62, 0x6E, 0xB4, 0x96, 0xCD, 0x13, 0x53, 0x4B, 0x28, 0xD7, 0xD1, 0x33, 0xB8, 0xE6, 0x7A, 0x2C, 0x9B, 0x29, 0x44, 0x52, 0xF7, 0x20, 0xF2, 0x31, 0xD3, 0xB9, 0x40, 0xD0, 0x34, 0xF5, 0x54, 0x1A, 0x01, 0xA1, 0x92,
        0xFC, 0x85, 0x07, 0xBE, 0xDD, 0xBC, 0x19, 0xF3, 0x36, 0xF6, 0x72, 0x98, 0x4C, 0x7D, 0xC7, 0xD4, 0x45, 0x4A, 0x9A, 0xC3, 0x8A, 0xE5, 0x50, 0x46, 0xCC, 0x68, 0x76, 0x67, 0xC9, 0x0E, 0x3C, 0x57, 0xF0, 0x22, 0xBF, 0x26, 0x84, 0x0D, 0x90, 0xA3, 0xAE, 0x3D, 0x1D, 0xC8, 0x91, 0x05, 0x87, 0x70, 0x08, 0x73, 0x21, 0x49, 0x55, 0x3E, 0x37, 0x23, 0x18, 0x56, 0xCE, 0x82, 0x38, 0x95, 0x78, 0xF8]
#load_data = [0xA7, 0x51, 0x68, 0x52, 0x85, 0x27, 0xFF, 0x31, 0x88, 0x87, 0xD2, 0xC7, 0xD3, 0x23, 0x3F, 0x52, 0x55, 0x10, 0x1F, 0xAF, 0x27, 0xF0, 0x94, 0x5C, 0xCD, 0x3F, 0x7A, 0x79, 0x9F, 0x2F, 0xF0, 0xE7, 0x45, 0xF0, 0x86, 0x3C, 0xF9, 0xB0, 0xEA, 0x6D, 0x90, 0x42, 0xF7, 0x91, 0xED, 0x3A, 0x9A, 0x7C, 0x01, 0x6B, 0x84, 0xDC, 0x6C, 0xC8, 0x43, 0x07, 0x5C, 0x08, 0xF7, 0xDF, 0xEB, 0xE3, 0xAE, 0xA4]
crypto_table = dict(zip(s0_255,range(0x100)))

#get order table
source = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{}'
replaced = 'HfVl{qPcCYNMoRi6D7Jr}espOL3FhwdWAtTGZba4Ugjvnx1QkKE2IS9yuz5BX08m'
revsere_table = [] #index是source在replace中的下标
for i in source:
    revsere_table.append(replaced.find(i))



cmp_data = [0x526851A7, 0x31FF2785, 0xC7D28788, 0x523F23D3, 0xAF1F1055, 0x5C94F027, 0x797A3FCD, 0xE7F02F9F, 0x3C86F045, 0x6DEAB0F9, 0x91F74290, 0x7C9A3AED, 0xDC846B01, 0x0743C86C, 0xDFF7085C, 0xA4AEE3EB]
tmp = []
for i in cmp_data:
    tmp+=de_cmp(i)
print(tmp)

for i in range(256):
    tmp = decrypt(tmp, crypto_table)
    tmp = reverse_order(tmp, revsere_table)
print(''.join(chr(i) for i in tmp))

其中python和C语言的位运算有所不同(对于符号位的处理) 所以需要使用np库

运行即可得到flag

flag是一个音乐网址 也算是一个小彩蛋吧

总结

有关加密算法由于太菜了不会逆 采用的是暴力的做法 相当于是00-ff的一个表 感觉以后遇到复杂的运算但又是按位加密的都可以这样做?

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值