SunshineCTF - warp
0x01
直接运行显示权限不够,sudo运行后显示监听本机的端口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/* WARNING: Enum "__rlimit_resource": Some values do not have unique names */
/* DWARF original prototype:
Result<(),_alloc::boxed::Box<dyn_core::error::Error,_alloc::alloc::Global>> main(void) */
Result<> __rustcall warp_ebpf::warp_ebpf::main(void)
{
&[u8] data;
rlimit rlim;
Ebpf ebpf;
Result<> residual;
Ebpf val;
String iface;
String val_1;
Result<> residual_3;
Result<> residual_4;
Result<> residual_5;
RingBuf<> rb;
Result<> residual_6;
RingBuf<> val_2;
RingBufItem item;
u8 buffer [33];
Event event;
String str;
Argument args [1];
Argument args_1 [1];
Result<> residual_7;
Xdp *prog;
Result<> residual_2;
Result<> residual_1;
rlimit64 local_8f8 [7];
ControlFlow<> local_888;
Result<> local_820;
undefined1 local_7b8 [104];
undefined1 local_750 [1872];
local_8f8[0].rlim_cur = 0xffffffffffffffff;
local_8f8[0].rlim_max = 0xffffffffffffffff;
setrlimit(__RLIMIT_MEMLOCK,local_8f8);
data.length = 0x51e0;
data.data_ptr = &DAT_002e5000;
aya::bpf::Ebpf::load(&local_820,data);
core::result::branch<>(&local_888,&local_820);
if (local_888._0_8_ != -0x7ffffffffffffff7) {
/* WARNING: Subroutine does not return */
memcpy(local_7b8,&local_888,0x68);
}
/* WARNING: Subroutine does not return */
memcpy(local_750,&local_888.field_0x8,0x60);
}
主体代码很少,但是其中有一些奇怪的部分:
1
2
aya::bpf::Ebpf::load(&local_820,data);
core::result::branch<>(&local_888,&local_820);
这是为了加载bpf代码,查看其加载的数据,发现了ELF开头的部分:
1
2
(venv13) woc@myarch:sunshine/warp $ file stage1.o
stage1.o: ELF 64-bit LSB relocatable, eBPF, version 1 (SYSV), with debug_info, not stripped
然而不能直接运行,因为这是eBPF llvm code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/* ether header : 14B */
undefined8 xdp_prog(uint *packet_start)
{
ulonglong uVar1;
bool bVar2;
ushort *data;
ulonglong uVar3;
longlong lVar4;
byte data_char;
ushort *puVar5;
ushort *header_length;
ushort local_21;
byte local_1f;
byte local_1e;
ushort local_1d;
byte local_1b;
byte local_1a;
ushort local_19;
byte local_17;
byte local_16;
ushort local_15;
byte local_13;
byte local_12;
ushort local_11;
byte local_f;
byte local_e;
ushort local_d;
byte local_b;
byte local_a;
ushort local_9;
byte local_7;
byte local_6;
ushort local_5;
header_length = (ushort *)(ulonglong)packet_start[1];
uVar3 = (ulonglong)*packet_start;
puVar5 = (ushort *)(uVar3 + 0xe);
if (((puVar5 <= header_length) && ((ushort *)(uVar3 + 0x22) <= header_length)) &&
(*(short *)(uVar3 + 0xc) == 8)) {
uVar1 = (ulonglong)*(byte *)puVar5 & 0xf;
if (0x13 < uVar1 * 4) {
/* TCP type */
if (*(char *)(uVar3 + 0x17) == '\x06') {
if (header_length < puVar5 + uVar1 * 2 + 10) {
return 2;
}
uVar3 = (ulonglong)(puVar5[uVar1 * 2 + 6] >> 2) & 0x3c;
puVar5 = (ushort *)((longlong)puVar5 + uVar3 + uVar1 * 4);
if (uVar3 < 0x14) {
return 2;
}
}
else {
if (*(char *)(uVar3 + 0x17) != '\x11') {
return 2;
}
puVar5 = puVar5 + uVar1 * 2 + 4;
}
/* Signature = 'W4rp' */
if (((puVar5 + 2 <= header_length) &&
(((ulonglong)*(byte *)((longlong)puVar5 + 3) << 0x18 | (ulonglong)(byte)puVar5[1] << 0x10
| (ulonglong)*puVar5) == L'\x70723457')) &&
(data = (ushort *)bpf_ringbuf_reserve(rb,0x21,0), data != (ushort *)0x0)) {
if ((((((puVar5 + 2 < header_length) &&
(*(byte *)data = (byte)puVar5[2], (ushort *)((longlong)puVar5 + 5) < header_length))
&& (((*(byte *)((longlong)data + 1) = *(byte *)((longlong)puVar5 + 5),
puVar5 + 3 < header_length &&
((((*(byte *)(data + 1) = (byte)puVar5[3],
(ushort *)((longlong)puVar5 + 7) < header_length &&
(*(byte *)((longlong)data + 3) = *(byte *)((longlong)puVar5 + 7),
puVar5 + 4 < header_length)) &&
(*(byte *)(data + 2) = (byte)puVar5[4],
(ushort *)((longlong)puVar5 + 9) < header_length)) &&
((*(byte *)((longlong)data + 5) = *(byte *)((longlong)puVar5 + 9),
puVar5 + 5 < header_length &&
(*(byte *)(data + 3) = (byte)puVar5[5],
(ushort *)((longlong)puVar5 + 0xb) < header_length)))))) &&
(*(byte *)((longlong)data + 7) = *(byte *)((longlong)puVar5 + 0xb),
puVar5 + 6 < header_length)))) &&
((*(byte *)(data + 4) = (byte)puVar5[6],
(ushort *)((longlong)puVar5 + 0xd) < header_length &&
(*(byte *)((longlong)data + 9) = *(byte *)((longlong)puVar5 + 0xd),
puVar5 + 7 < header_length)))) &&
(((*(byte *)(data + 5) = (byte)puVar5[7],
(ushort *)((longlong)puVar5 + 0xf) < header_length &&
(((*(byte *)((longlong)data + 0xb) = *(byte *)((longlong)puVar5 + 0xf),
puVar5 + 8 < header_length &&
(*(byte *)(data + 6) = (byte)puVar5[8],
(ushort *)((longlong)puVar5 + 0x11) < header_length)) &&
(*(byte *)((longlong)data + 0xd) = *(byte *)((longlong)puVar5 + 0x11),
puVar5 + 9 < header_length)))) &&
(((((*(byte *)(data + 7) = (byte)puVar5[9],
(ushort *)((longlong)puVar5 + 0x13) < header_length &&
(*(byte *)((longlong)data + 0xf) = *(byte *)((longlong)puVar5 + 0x13),
puVar5 + 10 < header_length)) &&
(*(byte *)(data + 8) = (byte)puVar5[10],
(ushort *)((longlong)puVar5 + 0x15) < header_length)) &&
((*(byte *)((longlong)data + 0x11) = *(byte *)((longlong)puVar5 + 0x15),
puVar5 + 0xb < header_length &&
(*(byte *)(data + 9) = (byte)puVar5[0xb],
(ushort *)((longlong)puVar5 + 0x17) < header_length)))) &&
((*(byte *)((longlong)data + 0x13) = *(byte *)((longlong)puVar5 + 0x17),
puVar5 + 0xc < header_length &&
(((*(byte *)(data + 10) = (byte)puVar5[0xc],
(ushort *)((longlong)puVar5 + 0x19) < header_length &&
(*(byte *)((longlong)data + 0x15) = *(byte *)((longlong)puVar5 + 0x19),
puVar5 + 0xd < header_length)) &&
(*(byte *)(data + 0xb) = (byte)puVar5[0xd],
(ushort *)((longlong)puVar5 + 0x1b) < header_length)))))))))) &&
(((*(byte *)((longlong)data + 0x17) = *(byte *)((longlong)puVar5 + 0x1b),
puVar5 + 0xe < header_length &&
(*(byte *)(data + 0xc) = (byte)puVar5[0xe],
(ushort *)((longlong)puVar5 + 0x1d) < header_length)) &&
((*(byte *)((longlong)data + 0x19) = *(byte *)((longlong)puVar5 + 0x1d),
puVar5 + 0xf < header_length &&
(((*(byte *)(data + 0xd) = (byte)puVar5[0xf],
(ushort *)((longlong)puVar5 + 0x1f) < header_length &&
(*(byte *)((longlong)data + 0x1b) = *(byte *)((longlong)puVar5 + 0x1f),
puVar5 + 0x10 < header_length)) &&
((*(byte *)(data + 0xe) = (byte)puVar5[0x10],
(ushort *)((longlong)puVar5 + 0x21) < header_length &&
(*(byte *)((longlong)data + 0x1d) = *(byte *)((longlong)puVar5 + 0x21),
puVar5 + 0x11 < header_length)))))))))) {
*(byte *)(data + 0xf) = (byte)puVar5[0x11];
if ((ushort *)((longlong)puVar5 + 0x23) < header_length) {
*(byte *)((longlong)data + 0x1f) = *(byte *)((longlong)puVar5 + 0x23);
}
}
lVar4 = 0;
do {
data_char = *(byte *)(lVar4 + 0x70723457) ^ 0x60;
if (0x20 < (longlong)(char)data_char) {
data_char = (char)(((longlong)(char)data_char + 0xeU & 0xffffffff) % 0x5e) + 0x21;
}
*(byte *)((longlong)&local_21 + lVar4) = data_char;
lVar4 = lVar4 + 1;
} while (lVar4 != 0x1e);
if (((((((ulonglong)*(byte *)((longlong)data + 7) << 0x18 | (ulonglong)(byte)data[3] << 0x10
| (ulonglong)data[2]) << 0x20 |
(ulonglong)*(byte *)((longlong)data + 3) << 0x18 | (ulonglong)(byte)data[1] << 0x10 |
(ulonglong)*data) !=
(((ulonglong)local_1a << 0x18 | (ulonglong)local_1b << 0x10 | (ulonglong)local_1d) <<
0x20 | (ulonglong)local_1e << 0x18 | (ulonglong)local_1f << 0x10 |
(ulonglong)local_21)) ||
((((ulonglong)*(byte *)((longlong)data + 0xf) << 0x18 |
(ulonglong)(byte)data[7] << 0x10 | (ulonglong)data[6]) << 0x20 |
(ulonglong)*(byte *)((longlong)data + 0xb) << 0x18 | (ulonglong)(byte)data[5] << 0x10
| (ulonglong)data[4]) !=
(((ulonglong)local_12 << 0x18 | (ulonglong)local_13 << 0x10 | (ulonglong)local_15) <<
0x20 | (ulonglong)local_16 << 0x18 | (ulonglong)local_17 << 0x10 |
(ulonglong)local_19))) ||
((((ulonglong)*(byte *)((longlong)data + 0x17) << 0x18 |
(ulonglong)(byte)data[0xb] << 0x10 | (ulonglong)data[10]) << 0x20 |
(ulonglong)*(byte *)((longlong)data + 0x13) << 0x18 | (ulonglong)(byte)data[9] << 0x10
| (ulonglong)data[8]) !=
(((ulonglong)local_a << 0x18 | (ulonglong)local_b << 0x10 | (ulonglong)local_d) << 0x20
| (ulonglong)local_e << 0x18 | (ulonglong)local_f << 0x10 | (ulonglong)local_11))) ||
((((ulonglong)*(byte *)((longlong)data + 0x1b) << 0x18 |
(ulonglong)(byte)data[0xd] << 0x10 | (ulonglong)data[0xc]) !=
((ulonglong)local_6 << 0x18 | (ulonglong)local_7 << 0x10 | (ulonglong)local_9) ||
(bVar2 = false, data[0xe] != local_5)))) {
bVar2 = true;
}
*(bool *)(data + 0x10) = !bVar2;
bpf_ringbuf_submit(data,0);
}
}
}
return 2;
}
其中大部分代码都是对packet进行解析,真正有用的在最后(着重看其中存在“比较”的逻辑,这里是连续的!=),这里看似字节比较是不连续的,其实只是反汇编后的变量编号问题。
bpf程序的数据很多在map中存储,可以用bpftool查看。 先运行程序,然后:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(venv13) woc@myarch:sunshine/warp $ sudo bpftool map show
11: hash_of_maps name cgroup_hash flags 0x0
key 8B value 4B max_entries 2048 memlock 165920B
pids systemd(1)
19: array name .rodata flags 0x80
key 4B value 46B max_entries 1 memlock 312B
frozen
pids warp(164315)
20: ringbuf name rb flags 0x0
key 0B value 0B max_entries 4096 memlock 16680B
pids warp(164315)
22: array name libbpf_global flags 0x0
key 4B value 32B max_entries 1 memlock 296B
23: array name pid_iter.rodata flags 0x480
key 4B value 4B max_entries 1 memlock 8192B
btf_id 265 frozen
pids bpftool(164377)
24: array name libbpf_det_bind flags 0x0
key 4B value 32B max_entries 1 memlock 296B
可以看到已经出现了和warp有关的map
1
2
3
4
5
6
7
8
(venv13) woc@myarch:sunshine/warp $ sudo bpftool map dump id 19
key:
00 00 00 00
value:
57 34 72 70 00 00 00 00 00 00 00 00 00 00 00 00
24 26 5f 2c 5f 3f 5f 50 58 21 00 50 11 41 15 50
54 20 55 56 50 58 3f 50 53 23 23 23 23 2e
Found 1 element
[TODO]能否不借助bpftool直接找出程序数据存放的位置?
This post is licensed under CC BY 4.0 by the author.
