虎符CTF 2022 部分re
压箱底的文章 才发现没发
别的队的wp!
https://mp.weixin.qq.com/s/fliCABrUziXEfWfgkG8mwA
https://mp.weixin.qq.com/s/cP03dJHppwEjo0o4B2bU6g
fpbe
知识点:ebpf bpf
https://www.cnblogs.com/lfri/p/15402973.html
https://www.cnblogs.com/davad/articles/bpf-btf-xiang-xi-jie-shao.html
BPF程序经过Clang/LLVM编译成BPF字节码,然后通过BPF系统调用的方式加载进内核
表面逻辑是
实际上16位sha256几乎不可能被爆破
真实逻辑是
hook了uprobed这个函数
根据前面bpf文章 可以找
fpbe_bpf__open_and_load()
fpbe_bpf__open()
fpbe_bpf__open_opts
fpbe_bpf__create_skeleton
(关于skeleton和rodata 参见https://nakryiko.com/posts/libbpf-bootstrap/ 译文 https://blog.csdn.net/sinat_38816924/article/details/122259826
)
拿到unk_4f4018
dump出即可
(
看到别的队的wp中有ida插件可以直接反编译ebpf的字节码
https://github.com/saaph/eBPF_processor
运行在python2环境下 (但是我并没有调明白ida调用python2的环境(
还有队伍使用了bpftool直接导出
)
我使用LLVM-odjdump -d dump.o
0000000000000000 <uprobe>:
0: 79 12 68 00 00 00 00 00 r2 = *(u64 *)(r1 + 104)
1: 67 02 00 00 20 00 00 00 r2 <<= 32
2: 77 02 00 00 20 00 00 00 r2 >>= 32
3: 79 13 70 00 00 00 00 00 r3 = *(u64 *)(r1 + 112)
4: 67 03 00 00 20 00 00 00 r3 <<= 32
5: 77 03 00 00 20 00 00 00 r3 >>= 32
6: bf 34 00 00 00 00 00 00 r4 = r3
7: 27 04 00 00 c0 6d 00 00 r4 *= 28096
8: bf 25 00 00 00 00 00 00 r5 = r2
9: 27 05 00 00 88 fb 00 00 r5 *= 64392
10: 0f 45 00 00 00 00 00 00 r5 += r4
11: 79 14 60 00 00 00 00 00 r4 = *(u64 *)(r1 + 96)
12: 67 04 00 00 20 00 00 00 r4 <<= 32
13: 77 04 00 00 20 00 00 00 r4 >>= 32
14: bf 40 00 00 00 00 00 00 r0 = r4
15: 27 00 00 00 fb 71 00 00 r0 *= 29179
16: 0f 05 00 00 00 00 00 00 r5 += r0
17: 79 11 58 00 00 00 00 00 r1 = *(u64 *)(r1 + 88)
18: b7 00 00 00 00 00 00 00 r0 = 0
19: 73 0a f8 ff 00 00 00 00 *(u8 *)(r10 - 8) = r0
20: 7b 0a f0 ff 00 00 00 00 *(u64 *)(r10 - 16) = r0
21: 7b 0a e8 ff 00 00 00 00 *(u64 *)(r10 - 24) = r0
22: 67 01 00 00 20 00 00 00 r1 <<= 32
23: 77 01 00 00 20 00 00 00 r1 >>= 32
24: bf 10 00 00 00 00 00 00 r0 = r1
25: 27 00 00 00 8e cc 00 00 r0 *= 52366
26: 0f 05 00 00 00 00 00 00 r5 += r0
27: b7 06 00 00 01 00 00 00 r6 = 1
28: 18 00 00 00 95 59 73 a1 00 00 00 00 18 be 00 00 r0 = 209012997183893 ll
30: 5d 05 42 00 00 00 00 00 if r5 != r0 goto +66 <LBB0_5>
31: bf 35 00 00 00 00 00 00 r5 = r3
32: 27 05 00 00 bf f1 00 00 r5 *= 61887
33: bf 20 00 00 00 00 00 00 r0 = r2
34: 27 00 00 00 e5 6a 00 00 r0 *= 27365
35: 0f 50 00 00 00 00 00 00 r0 += r5
36: bf 45 00 00 00 00 00 00 r5 = r4
37: 27 05 00 00 d3 ad 00 00 r5 *= 44499
38: 0f 50 00 00 00 00 00 00 r0 += r5
39: bf 15 00 00 00 00 00 00 r5 = r1
40: 27 05 00 00 84 92 00 00 r5 *= 37508
41: 0f 50 00 00 00 00 00 00 r0 += r5
42: 18 05 00 00 40 03 54 e5 00 00 00 00 56 a5 00 00 r5 = 181792633258816 ll
44: 5d 50 34 00 00 00 00 00 if r0 != r5 goto +52 <LBB0_5>
45: bf 35 00 00 00 00 00 00 r5 = r3
46: 27 05 00 00 85 dd 00 00 r5 *= 56709
47: bf 20 00 00 00 00 00 00 r0 = r2
48: 27 00 00 00 28 80 00 00 r0 *= 32808
49: 0f 50 00 00 00 00 00 00 r0 += r5
50: bf 45 00 00 00 00 00 00 r5 = r4
51: 27 05 00 00 2d 65 00 00 r5 *= 25901
52: 0f 50 00 00 00 00 00 00 r0 += r5
53: bf 15 00 00 00 00 00 00 r5 = r1
54: 27 05 00 00 12 e7 00 00 r5 *= 59154
55: 0f 50 00 00 00 00 00 00 r0 += r5
56: 18 05 00 00 a3 4d 48 74 00 00 00 00 f3 a6 00 00 r5 = 183564558159267 ll
58: 5d 50 26 00 00 00 00 00 if r0 != r5 goto +38 <LBB0_5>
59: bf 35 00 00 00 00 00 00 r5 = r3
60: 27 05 00 00 2c 82 00 00 r5 *= 33324
61: bf 20 00 00 00 00 00 00 r0 = r2
62: 27 00 00 00 43 ca 00 00 r0 *= 51779
63: 0f 50 00 00 00 00 00 00 r0 += r5
64: bf 45 00 00 00 00 00 00 r5 = r4
65: 27 05 00 00 8e 7c 00 00 r5 *= 31886
66: 0f 50 00 00 00 00 00 00 r0 += r5
67: bf 15 00 00 00 00 00 00 r5 = r1
68: 27 05 00 00 3a f2 00 00 r5 *= 62010
69: 0f 50 00 00 00 00 00 00 r0 += r5
70: 18 05 00 00 77 72 5a 48 00 00 00 00 9c b9 00 00 r5 = 204080879923831 ll
72: 5d 50 18 00 00 00 00 00 if r0 != r5 goto +24 <LBB0_5>
73: 63 1a f4 ff 00 00 00 00 *(u32 *)(r10 - 12) = r1
74: 63 4a f0 ff 00 00 00 00 *(u32 *)(r10 - 16) = r4
75: 63 2a ec ff 00 00 00 00 *(u32 *)(r10 - 20) = r2
76: 63 3a e8 ff 00 00 00 00 *(u32 *)(r10 - 24) = r3
77: 18 01 00 00 43 54 46 7b 00 00 00 00 25 73 7d 0a r1 = 755886917287302211 ll
79: 7b 1a d8 ff 00 00 00 00 *(u64 *)(r10 - 40) = r1
80: 18 01 00 00 46 4c 41 47 00 00 00 00 3a 20 48 46 r1 = 5064333215653776454 ll
82: 7b 1a d0 ff 00 00 00 00 *(u64 *)(r10 - 48) = r1
83: 18 01 00 00 45 21 20 59 00 00 00 00 4f 55 52 20 r1 = 2329017756590022981 ll
85: 7b 1a c8 ff 00 00 00 00 *(u64 *)(r10 - 56) = r1
86: 18 01 00 00 57 45 4c 4c 00 00 00 00 20 44 4f 4e r1 = 5642803763628229975 ll
88: 7b 1a c0 ff 00 00 00 00 *(u64 *)(r10 - 64) = r1
89: b7 06 00 00 00 00 00 00 r6 = 0
90: 73 6a e0 ff 00 00 00 00 *(u8 *)(r10 - 32) = r6
91: bf a1 00 00 00 00 00 00 r1 = r10
92: 07 01 00 00 c0 ff ff ff r1 += -64
93: bf a3 00 00 00 00 00 00 r3 = r10
94: 07 03 00 00 e8 ff ff ff r3 += -24
95: b7 02 00 00 21 00 00 00 r2 = 33
96: 85 00 00 00 06 00 00 00 call 6
0000000000000308 <LBB0_5>:
97: bf 60 00 00 00 00 00 00 r0 = r6
98: 95 00 00 00 00 00 00 00 exit
逻辑比较简单
from z3 import *
s = Solver()
flag = [BitVec('%d' % i, 32) for i in range(4)]
s.add(flag[0] * 52366 + flag[1] * 29179 + flag[2] * 28096 + flag[3] * 64392 == 209012997183893)
s.add(flag[0] * 37508 + flag[1] * 44499 + flag[2] * 61887 + flag[3] * 27365 == 181792633258816)
s.add(flag[0] * 59154 + flag[1] * 25901 + flag[2] * 56709 + flag[3] * 32808 == 183564558159267)
s.add(flag[0] * 62010 + flag[1] * 31886 + flag[2] * 33324 + flag[3] * 51779 == 204080879923831)
if s.check() == sat:
s = s.model()
for i in range(4):
result = s[flag[i]].as_long().real
print(hex(result))
shellcode
x64dbg 动调
scyllahide插件选themida
scylla直接dump下来分析
字符串定位
长度0x160 v39是个快速base64算法 动调也容易看出
中间一路先略过
来到94行
先rol3
一个很像xxtea 但是>>6
最后比较
#include <iostream>
#include <string>
#include <fstream>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;
uint32_t key[4] = {'t', 'o', 'r', 'a'};
#define MX (((z >> 6 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum ^ y) + (key[(p & 3) ^ e] ^ z)))
#define DELTA 0x9e3779b9
void btea(uint32_t *v, int n, uint32_t key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) /* Coding Part */
{
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do
{
sum += DELTA;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p++)
{
y = v[p + 1];
uint32_t tmp = MX;
v[p] += tmp;
z = v[p];
}
y = v[0];
z = v[n - 1] += MX;
} while (--rounds);
}
else if (n < -1) /* Decoding Part */
{
n = -n;
rounds = 6 + 52 / n;
sum = rounds * DELTA;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--)
{
z = v[p - 1];
v[p] -= MX;
y = v[p];
}
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
} while (--rounds);
}
}
// ror byte
uint8_t ror(uint8_t x, uint8_t n)
{
return (x >> n) | (x << (8 - n));
}
const char *base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// base64加密
string base64_encode(const string &str)
{
string out;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (i < str.size())
{
char_array_3[0] = str.at(i++);
char_array_3[1] = str.at(i++);
char_array_3[2] = str.at(i++);
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; (j < 4); j++)
out += base64_chars[char_array_4[j]];
}
while ((out.size() % 4) != 0)
out += "=";
return out;
}
int main(int argc, char const *argv[])
{
uint32_t enc[66] = {
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};
btea((uint32_t *)enc, -66, key);
//打印enc
for (int i = 0; i < 66; i++)
{
// printf("0x%08x,", enc[i]);
}
uint8_t *str = (uint8_t *)enc;
// str每项都ror3
for (int i = 0; i < 66 * 4; i++)
{
str[i] = ror(str[i], 3);
}
//打印str
for (int i = 0; i < 66 * 4; i++)
{
printf("0x%02x,", str[i]);
}
printf("\n");
//将str转为string
string s = string((char *)str, 66 * 4);
//加密
string base64_str = base64_encode(s);
//打印base64_str
printf("%s\n", base64_str.c_str());
}
拿到shellcode
之后就是执行该shellcode
写一个执行shellcode的demo
#include <stdio.h>
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, 00, 00, 00, 0x3, 0xc2, 0x50, 0x8b, 0x48, 0x18, 0x8b, 0x58, 0x20, 0x3, 0xda, 0x83, 0xf9, 00, 0xf, 0x84, 0xa9, 00, 00, 00, 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, 00, 00, 0x8b, 0xc4, 0x68, 0x6e, 0x6f, 00, 00, 0x54, 0x50, 0x8b, 0x5c, 0x24, 0x48, 0xff, 0xd3, 0xeb, 0x14, 0x68, 0x25, 0x73, 00, 00, 0x8b, 0xc4, 0x68, 0x79, 0x65, 0x73, 00, 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 };
int main()
{
__asm {
lea eax, shellcode;
push eax;
ret
}
return 0;
}
并用010或其他工具更改区段为可读可写可执行
ida动调分析即可
#include <iostream>
#include <string>
#include <fstream>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <vector>
using namespace std;
int main(int argc, char const *argv[])
{
char *a = "LoadLibraryExA";
char *b = "is program can";
char *c = (char *)malloc(strlen(a));
// c[i] = a[i]%5 + b[i];
for (int i = 0; i < strlen(a); i++)
{
c[i] = a[i] % 5 + b[i];
}
printf("%s\n", c);
}
至此 两部分相加md5即可