IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 2022虎符 the_shellcode -> 正文阅读

[C++知识库]2022虎符 the_shellcode

ida attach 到进程上,然后把数据改为代码形式然后 F5 反汇编。
在这里插入图片描述
主体逻辑如下:

int __usercall sub_1711BF@<eax>(int a1@<edi>, int a2@<esi>)
{
  unsigned int v3; // ebx
  _DWORD *v4; // eax
  _DWORD *v5; // edi
  unsigned int v6; // esi
  unsigned int i; // ecx
  signed int v8; // ebx
  unsigned int v9; // ecx
  int v10; // edx
  int v11; // eax
  unsigned int v12; // ebx
  bool v13; // zf
  int v14; // ebx
  unsigned int v15; // esi
  __m128i *v16; // eax
  __m128i v17; // xmm3
  __m128i v18; // xmm2
  __m128i v19; // xmm0
  __m128i v20; // xmm1
  __m128i v21; // xmm1
  __m128i v22; // xmm0
  __m128i v23; // xmm2
  __m128i v24; // xmm2
  int v25; // ecx
  unsigned int v26; // esi
  int v27; // eax
  void (__cdecl *v28)(int (*)(int, ...), __int64 *); // ebx
  _BYTE *v29; // esi
  int v32; // [esp-1BCh] [ebp-1BCh]
  _DWORD *v33; // [esp-1B4h] [ebp-1B4h]
  unsigned int v34; // [esp-1B0h] [ebp-1B0h]
  int v35; // [esp-1ACh] [ebp-1ACh]
  unsigned int v36; // [esp-1A8h] [ebp-1A8h]
  unsigned int v37; // [esp-1A4h] [ebp-1A4h]
  unsigned int *v38; // [esp-1A0h] [ebp-1A0h]
  int v39; // [esp-19Ch] [ebp-19Ch]
  unsigned int v40; // [esp-198h] [ebp-198h] BYREF
  _BYTE *v41; // [esp-194h] [ebp-194h]
  unsigned int vlp; // [esp-190h] [ebp-190h]
  int key[4]; // [esp-18Ch] [ebp-18Ch]
  char input[356]; // [esp-17Ch] [ebp-17Ch] BYREF
  __int64 v45; // [esp-18h] [ebp-18h] BYREF
  int v46; // [esp-10h] [ebp-10h]
  __int16 v47; // [esp-Ch] [ebp-Ch]
  char v48; // [esp-Ah] [ebp-Ah]
  unsigned int v49; // [esp-8h] [ebp-8h]
  int v50; // [esp-4h] [ebp-4h] BYREF

  __debugbreak();
  v49 = (unsigned int)&v50 ^ dword_174004;
  memset((int)input, 0, 353);
  printf((int)"please input the shellcode:\n");
  scanf("%352s", input);
  if ( &input[strlen(input) + 1] - &input[1] != 352 )
  {
    printf((int)"shellcode length error\n");
LABEL_3:
    (*(&loc_173098 + 1))("pause");
    return sub_17166E((char)v33);
  }
  v40 = 352;
  v41 = base64(352u, input, (int *)&v40);
  if ( (v40 & 3) != 0 )
    v3 = 4 * (v40 >> 2) + 4;
  else
    v3 = v40;
  v4 = (_DWORD *)ucrtbase_malloc(v3);
  v5 = v4;
  v33 = v4;
  if ( !v4 )
    return sub_17166E((char)v33);
  memset((int)v4, 0, v3);
  v6 = v40;
  if ( v40 )
  {
    if ( v41 && v3 >= v40 )
    {
      memcpy((int)v5, (int)v41, v40);
      goto LABEL_17;
    }
    memset((int)v5, 0, v3);
    if ( v41 )
    {
      if ( v3 >= v6 )
        goto LABEL_17;
      *(_DWORD *)sub_1A398C() = '"';
    }
    else
    {
      *(_DWORD *)sub_1A398C() = '\x16';
    }
    sub_254ACA();
  }
LABEL_17:
  for ( i = 0; i < v3; ++i )
    *((_BYTE *)v5 + i) = __ROL1__(*((_BYTE *)v5 + i), 3);
  v8 = v3 >> 2;
  key[0] = 116;
  key[1] = 111;
  v38 = &v5[v8 - 1];
  v9 = v5[v8 - 1];
  v10 = v8 - 1;
  v35 = 52 / v8 + 6;
  v11 = 0;
  key[2] = 114;
  key[3] = 97;
  v37 = v8;
  vlp = v9;
  v34 = v8 - 1;
  do
  {
    v12 = 0;
    v39 = v11 - 0x61C88647;
    v36 = ((unsigned int)(v11 - 0x61C88647) >> 2) & 3;
    if ( v10 )
    {
      do
      {
        v5[v12] += ((v39 ^ v5[v12 + 1]) + (vlp ^ key[v36 ^ v12 & 3])) ^ (((16 * vlp) ^ (v5[v12 + 1] >> 3))
                                                                       + ((v9 >> 6) ^ (4 * v5[v12 + 1])));
        v9 = v5[v12++];
        vlp = v9;
      }
      while ( v12 < v34 );
    }
    v10 = v34;
    *v38 += ((v39 ^ *v5) + (vlp ^ key[v36 ^ v12 & 3])) ^ (((16 * vlp) ^ (*v5 >> 3)) + ((v9 >> 6) ^ (4 * *v5)));
    v13 = v35-- == 1;
    v9 = *v38;
    v11 -= 0x61C88647;
    vlp = *v38;
  }
  while ( !v13 );
  v14 = 0;
  v15 = 0;
  if ( !v37 )
    goto LABEL_38;
  if ( v37 >= 8 )
  {
    v16 = (__m128i *)v5;
    v17 = 0i64;
    v18 = 0i64;
    do
    {
      v19 = *v16;
      v15 += 8;
      v16 += 2;
      v20 = _mm_cmpeq_epi32(*(__m128i *)((char *)&v16[-2] + (char *)dword_173310 - (char *)v5), v19);
      v17 = _mm_or_si128(_mm_and_si128(_mm_add_epi32((__m128i)xmmword_173420, v17), v20), _mm_andnot_si128(v20, v17));
      v21 = _mm_cmpeq_epi32(*(__m128i *)((char *)&v16[-2] + &unk_173320 - (_UNKNOWN *)v5), v16[-1]);
      v22 = _mm_or_si128(_mm_and_si128(_mm_add_epi32((__m128i)xmmword_173420, v18), v21), _mm_andnot_si128(v21, v18));
      v18 = v22;
    }
    while ( v15 < (v37 & 0xFFFFFFF8) );
    v5 = v33;
    v23 = _mm_add_epi32(v22, v17);
    v24 = _mm_add_epi32(v23, _mm_srli_si128(v23, 8));
    v14 = _mm_cvtsi128_si32(_mm_add_epi32(v24, _mm_srli_si128(v24, 4)));
  }
  for ( ; v15 < v37; v14 = v25 )
  {
    v25 = v14 + 1;
    if ( dword_173310[v15] != v5[v15] )
      v25 = v14;
    ++v15;
  }
  if ( v14 != 66 )
  {
LABEL_38:
    printf((int)"wrong shellcode\n");
    goto LABEL_39;
  }
  printf((int)"now let's execute the shellcode\n");
  printf((int)&off_1731A8);
  v46 = 0;
  v47 = 0;
  v45 = 0i64;
  v48 = 0;
  scanf("%14s", &v45);
  if ( strlen((const char *)&v45) != 14 )
  {
    printf((int)"length error\n");
LABEL_39:
    ucrtbase_free(v41);
    ucrtbase_free(v5);
    (*(&loc_173098 + 1))("pause");
    return sub_17166E((char)v33);
  }
  v26 = v40;
  v27 = ((int (__fastcall *)(int, char *, _DWORD, unsigned int, int, int, int, int))((char *)&loc_2D39B6 + 2))(
          14,
          (char *)&v45 + 1,
          0,
          v40,
          4096,
          64,
          a1,
          a2);
  v28 = (void (__cdecl *)(int (*)(int, ...), __int64 *))v27;
  if ( v27 )
  {
    v32 = v26;
    v29 = v41;
    memcpy(v27, (int)v41, v32);
    v28(printf, &v45);
    ucrtbase_free(v29);
    ucrtbase_free(v5);
    sub_1D8CC6(v28);
    printf((int)&off_1731D4);
    goto LABEL_3;
  }
  return sub_17166E(v35);
}

检查完读入长度后首先对输入进行 base64 解码:
在这里插入图片描述
之后把数据每一字节都循环左移 3 位:
在这里插入图片描述
之后就是一个 XXTEA 加密:

 v8 = v3 >> 2;
  key[0] = 116;
  key[1] = 111;
  v38 = &v5[v8 - 1];
  v9 = v5[v8 - 1];
  v10 = v8 - 1;
  v35 = 52 / v8 + 6;
  v11 = 0;
  key[2] = 114;
  key[3] = 97;
  v37 = v8;
  vlp = v9;
  v34 = v8 - 1;
  do
  {
    v12 = 0;
    v39 = v11 - 0x61C88647;
    v36 = ((unsigned int)(v11 - 0x61C88647) >> 2) & 3;
    if ( v10 )
    {
      do
      {
        v5[v12] += ((v39 ^ v5[v12 + 1]) + (vlp ^ key[v36 ^ v12 & 3])) ^ (((16 * vlp) ^ (v5[v12 + 1] >> 3))
                                                                       + ((v9 >> 6) ^ (4 * v5[v12 + 1])));
        v9 = v5[v12++];
        vlp = v9;
      }
      while ( v12 < v34 );
    }
    v10 = v34;
    *v38 += ((v39 ^ *v5) + (vlp ^ key[v36 ^ v12 & 3])) ^ (((16 * vlp) ^ (*v5 >> 3)) + ((v9 >> 6) ^ (4 * *v5)));
    v13 = v35-- == 1;
    v9 = *v38;
    v11 -= 0x61C88647;
    vlp = *v38;
  }
  while ( !v13 );

需要注意的是这里的 XXTEA 是魔改过的,共有 3 处修改:

  • delta0x9E3779B9 改为了 0x61C88647
  • v11 += delta; 这里变成了 v11 -= delta;
  • v9 >> 5 改为了 v9 >> 6

后面有一个比较:
在这里插入图片描述
对应如下数据:
在这里插入图片描述

根据以上分析不难写出逆向脚本:

#include <bits/stdc++.h>

using namespace std;
#define ROR3(x) (((x)>>3) | (((x)&7) << 5))
typedef unsigned int i32;
typedef unsigned char i8;

struct XXTEA {
    const i32 delta = 0x61C88647;

    inline void decryptData(vector<i32> &v, vector<i32> k) {
        while (k.size() < 4)k.push_back(0);
        i32 t = 6 + 52 / v.size();
        for (i32 i = 0, sum = -delta * t; i < t; i++, sum += delta)
            for (int p = (int) v.size() - 1; p >= 0; p--) {
                int lp = p - 1, rp = p + 1;
                if (lp < 0)lp += (int) v.size();
                if (rp >= v.size())rp -= (int) v.size();
                v[p] -= (((v[lp] >> 6 ^ v[rp] << 2) + (v[rp] >> 3 ^ v[lp] << 4)) ^
                         ((sum ^ v[rp]) + (k[(p & 3) ^ (sum >> 2 & 3)] ^ v[lp])));
            }
    }

    inline vector<i8> decryptString(vector<i32> &v, vector<i32> k) {
        assert(v.size() % 2 == 0);
        while (k.size() < 4)k.push_back(0);
        decryptData(v, k);
        return intToString(v);
    }

    inline vector<i8> intToString(vector<i32> &v) {
        vector<i8> s;
        for (int i = 0; i < v.size(); i++) {
            s.push_back(i8(v[i] & 0xFF));
            s.push_back(i8(v[i] >> 8 & 0xFF));
            s.push_back(i8(v[i] >> 16 & 0xFF));
            s.push_back(i8(v[i] >> 24 & 0xFF));
        }
        return s;
    }
} T;

struct Base64 {
    string table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    string encode(vector<i8> s) {
        string res;
        int n = (int) s.size();
        s.push_back('\x00');
        for (int i = 0; i < n; i += 3) {
            res.push_back(table[s[i] >> 2]);
            res.push_back(table[((s[i] & 3) << 4) | (s[i + 1] >> 4)]);
            if (i + 1 < n)res.push_back(table[((s[i + 1] & 15) << 2) | (s[i + 2] >> 6)]);
            if (i + 2 < n)res.push_back(table[s[i + 2] & ((1 << 6) - 1)]);
        }
        while (res.size() & 3)res.push_back('=');
        return res;
    }
} B;

int main() {
    vector<unsigned int> v = {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};
    vector<unsigned int> k = {116, 111, 114, 97};
    vector<i8> t = T.decryptString(v, k);
    for (int i = 0; i < t.size(); i++)t[i] = ROR3(t[i]);
    for (int i = 0; i < t.size(); i++)
        cout << hex << "0x" << int(t[i]) << ",\n"[i == (int) t.size() - 1];
    string s = B.encode(t);
    cout << s << "\n";
    return 0;
}

解得 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,0x0,0x0,0x0,0x3,0xc2,0x50,0x8b,0x48,0x18,0x8b,0x58,0x20,0x3,0xda,0x83,0xf9,0x0,0xf,0x84,0xa9,0x0,0x0,0x0,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,0x0,0x0,0x8b,0xc4,0x68,0x6e,0x6f,0x0,0x0,0x54,0x50,0x8b,0x5c,0x24,0x48,0xff,0xd3,0xeb,0x14,0x68,0x25,0x73,0x0,0x0,0x8b,0xc4,0x68,0x79,0x65,0x73,0x0,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 编码后的 shellcode 输入为:

YPxoTHcmBzPSZItSMItSDItSFItyKA+3SiYz/zPArDxhfAIsIMHPDQP44vBSV4tSEItCPAPCi0B4hcAPhL4AAAADwlCLSBiLWCAD2oP5AA+EqQAAAEmLNIsD8jP/M8Cswc8NA/g6xHX0A3wkBDt8JAx12TP/M8mDwlAPtgQKwc8NA/hBg/kOdfHBzw1XM/8zyYtUJDxSD7YcDrhnZmZm9+vR+ovCwegfA8KNBIAr2FoPtgQKK8PBzw0D+EGD+Q511MHPDTs8JHQWaCVzAACLxGhubwAAVFCLXCRI/9PrFGglcwAAi8RoeWVzAFRQi1wkSP/TWFhYWFhYWFhYYcNYX1qLEukL

将 shellcode 运行起来然后 ida 动调
编译命令:

gcc shellcode.c -o shellcode.exe -g -m32
#include <windows.h>
#include <string.h>

unsigned char 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};

typedef void(__stdcall *CODE)();

int main() {
    PVOID p = NULL;
    if ((p = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)) == NULL)
        MessageBoxA(NULL, "alloc error", "tips", MB_OK);
    if (!(memcpy(p, shellcode, sizeof(shellcode))))
        MessageBoxA(NULL, "write error", "tips", MB_OK);
    CODE code = (CODE) p;
    code();
    return 0;
}

shellcode 反编译代码为:

void __usercall shellcode(int eax0@<eax>, int edx0@<edx>, int a3@<ecx>, void (__cdecl *a1)(int *, int *), char *flag)
{
  _LIST_ENTRY *i; // edx
  _LIST_ENTRY *Flink; // esi
  int Blink_high; // ecx
  int v8; // edi
  int Flink_low; // eax
  _LIST_ENTRY *v10; // edx
  int v11; // eax
  int v12; // ecx
  char *v13; // ebx
  unsigned __int8 *v14; // esi
  int v15; // edi
  int v16; // eax
  int v17; // edi
  int v18; // ecx
  _LIST_ENTRY *v19; // edx
  int v20; // edi
  int j; // ecx
  int v22; // [esp-8h] [ebp-3Ch] BYREF
  int v23; // [esp-4h] [ebp-38h] BYREF
  int v24; // [esp+0h] [ebp-34h]
  int v25; // [esp+4h] [ebp-30h]
  int v26; // [esp+8h] [ebp-2Ch]
  _LIST_ENTRY *v27; // [esp+Ch] [ebp-28h]
  int v28; // [esp+10h] [ebp-24h]
  int v29; // [esp+14h] [ebp-20h]
  int v30; // [esp+18h] [ebp-1Ch]
  int v31; // [esp+1Ch] [ebp-18h]
  void **v32; // [esp+24h] [ebp-10h]
  void *retaddr; // [esp+34h] [ebp+0h] BYREF

  v32 = &retaddr;
  v31 = a3;
  v30 = edx0;
  v29 = eax0;
  v28 = 119961420;
  for ( i = NtCurrentPeb()->Ldr->InMemoryOrderModuleList.Flink; ; i = v27->Flink )
  {
    Flink = i[5].Flink;
    Blink_high = HIWORD(i[4].Blink);
    v8 = 0;
    do
    {
      Flink_low = LOBYTE(Flink->Flink);
      Flink = (_LIST_ENTRY *)((char *)Flink + 1);
      if ( (char)Flink_low >= 97 )
        LOBYTE(Flink_low) = Flink_low - 32;
      v8 = Flink_low + __ROR4__(v8, 13);
      --Blink_high;
    }
    while ( Blink_high );
    v27 = i;
    v26 = v8;
    v10 = i[2].Flink;
    v11 = *(int *)((char *)&v10[15].Flink + (unsigned int)v10[7].Blink);
    if ( v11 )
      break;
LABEL_20:
    ;
  }
  v25 = (int)v10 + v11;
  v12 = *(int *)((char *)&v10[3].Flink + v11);
  v13 = (char *)v10 + *(unsigned int *)((char *)&v10[4].Flink + v11);
  do
  {
    if ( !v12 )
      goto LABEL_20;
    --v12;
    v14 = (unsigned __int8 *)v10 + *(_DWORD *)&v13[4 * v12];
    v15 = 0;
    do
    {
      v16 = *v14++;
      v15 = v16 + __ROR4__(v15, 13);
    }
    while ( (_BYTE)v16 != BYTE1(v16) );
  }
  while ( v26 + v15 != v28 );
  v17 = 0;
  v18 = 0;
  v19 = v10 + 10;
  do
    v17 = *((unsigned __int8 *)&v19->Flink + v18++) + __ROR4__(v17, 13);
  while ( v18 != 14 );
  v24 = __ROR4__(v17, 13);
  v20 = 0;
  for ( j = 0; j != 14; ++j )
  {
    v23 = (int)flag;
    v20 = (unsigned __int8)flag[j] - v14[j] % 5 + __ROR4__(v20, 13);
  }
  v23 = 29477;
  if ( __ROR4__(v20, 13) == v24 )
    v22 = 7562617;
  else
    v22 = 28526;
  a1(&v23, &v22);
}

前面部分是初始化数据,获取加密所用的字符串。
关键代码为:

  v17 = 0;
  v18 = 0;
  v19 = v10 + 10;
  do
    v17 = *((unsigned __int8 *)&v19->Flink + v18++) + __ROR4__(v17, 13);
  while ( v18 != 14 );
  v24 = __ROR4__(v17, 13);
  v20 = 0;
  for ( j = 0; j != 14; ++j )
  {
    v23 = (int)flag;
    v20 = (unsigned __int8)flag[j] - v14[j] % 5 + __ROR4__(v20, 13);
  }
  v23 = 29477;
  if ( __ROR4__(v20, 13) == v24 )
    v22 = 7562617;
  else
    v22 = 28526;

可以看出,这里分别对 &v19->Flink 的前 14 个字符做一个哈希运算,结果为 v24
之后对 flag[j] - v14[j] % 5 前 14 个结果做一个哈希运算,结果为 __ROR4__(v20, 13)
最后比较这两个哈希的结果,盲猜如果相等则通过检验。
ida 动态调试:
定位到 &v19->Flink(即下面的 &v17->Flink
在这里插入图片描述
分析汇编
在这里插入图片描述
定位到对应的字符串
在这里插入图片描述
定位到 v14(单跑 shellcode ,执行到下一条语句会段错误,不过还是能够找到字符串)
在这里插入图片描述
在这里插入图片描述
如果两个序列相等,则哈希值相等,因此我们不妨认为两个序列相等,则 flag[i] = &v19->Flink[i] + v14[i] % 5

#include <bits/stdc++.h>

using namespace std;

int main() {
    string a = "is program cannot be run in DOS mode.";
    string b = "LoadLibraryExA";
    for (int i = 0; i < 14; i++)
        cout << char(a[i] + b[i] % 5);
    return 0;
}

求解得 flag 为

jt"psojvcq!gan

通过检验
在这里插入图片描述

与前面的 shellcode 拼接后求 md5 得 flag 为 HFCTF{2b794e95022f2fe46106c21bbf57a755}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-24 00:18:35  更:2022-03-24 00:20:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:37:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码