☆ XorDDoS某样本
参看
有VirusTotal企业账号的,可下载该ELF样本,也可尝试从微步在线下载。
用IDA32反汇编,样本没有strip,留有调试符号。
样本含有一些加密字符串,dec_conf()用于解密字符串。
dst用于保存解密结果,src是固化在.rodata中的加密数据,size对应src的长度。dec_conf()实际调用encrypt_code()完成解密。
encrypt_code()并不复杂,就是简单异或,xorkeys内置在ELF中,固定。但我们假设encrypt_code()很复杂,比如被控制流平坦化过,不想静态分析其逻辑,准备用angr模拟调用dec_conf()或encrypt_code(),黑盒调用,只关心in/out。
样本不只调用dec_conf()解密字符串,也会直接调用encrypt_code()解密字符串。下面是几处直接调用encrypt_code()解密字符串的地方:
还有其他调用encrypt_code()解密字符串的地方,但那些地方都是动态提供输入,不是固定串,此处略过。
☆ 用r2pipe模块静态分析
关于r2pipe模块,参看
1) 获取函数入口/出口地址
将来angr模拟调用dec_conf(),至少有两种方案。一种需要知道函数入口/出口地址,另一种只需知道函数入口地址。
假设已打开r2句柄,此处简化处理,假设ret是最后一条指令。
2) 获取到指定函数的交叉引用
样本调用dec_conf()的模式是固定的,只要找到"call dec_conf"指令所在地址,可从附近的汇编指令析取dec_conf()的参数,比如加密字符串的地址、长度。通过交叉引用找出所有"call dec_conf"指令所在地址。
3) 析取dec_conf()的参数
此实现只针对调用dec_conf()的情形,意思是,从"call dec_conf"向低址方向移动四条指令,反汇编这四条指令,分别析取第二条、第一条指令的立即数。
假设处理上述代码片段,get_call_params()将返回(0x80b2fb1,0xb),此即一条加密字符串,分别是地址、长度。
4) static_analyses()
将前面的小模块整合到一起,完成r2pipe静态分析
用r2分析样本,比用angr的CFGFast分析样本快得多。
☆ 用angr模拟调用dec_conf()
参看
angr至少有两种模拟调用dec_conf()的办法,分别是call_state、callable。前者控制粒度更细,比如执行到函数中部某个位置便停止模拟;后者使用起来更简洁。
1) proj.factory.call_state
sm.explore()的find参数可位于函数中部某个位置,不一定是ret指令所在地址。
2) proj.factory.callable
用callable时,无需知道函数出口地址。
☆ r2pipe+angr
将前面的小模块整合到一起
正常的话,应该输出
☆ 用angr模拟调用encrypt_code()
☆ 后记
据小宋说,XorDDoS家族现仍在活跃,但流行变种已将原始版本的rootkit部分移除。
本文目的并非分析XorDDoS样本,仅视之为Angr符号执行的练习目标,毕竟是现实世界逆向工程真实案例,而非CTF案例。
本文学习目的是黑盒式模拟调用关键函数,尝试获取函数结果。
方便测试,附件是样本,infected
创建:
2025
-
04
-
24
22
:
26
更新:
2025
-
04
-
25
19
:
04
目录:
☆ XorDDoS某样本
☆ 用r2pipe模块静态分析
1
) 获取函数入口
/
出口地址
2
) 获取到指定函数的交叉引用
3
) 析取dec_conf()的参数
4
) static_analyses()
☆ 用angr模拟调用dec_conf()
1
) proj.factory.call_state
2
) proj.factory.
callable
☆ r2pipe
+
angr
☆ 用angr模拟调用encrypt_code()
☆ 后记
创建:
2025
-
04
-
24
22
:
26
更新:
2025
-
04
-
25
19
:
04
目录:
☆ XorDDoS某样本
☆ 用r2pipe模块静态分析
1
) 获取函数入口
/
出口地址
2
) 获取到指定函数的交叉引用
3
) 析取dec_conf()的参数
4
) static_analyses()
☆ 用angr模拟调用dec_conf()
1
) proj.factory.call_state
2
) proj.factory.
callable
☆ r2pipe
+
angr
☆ 用angr模拟调用encrypt_code()
☆ 后记
XorDDoS僵尸网络家族的某样本
https:
/
/
7cdK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6i4k6A6M7Y4g2K6N6r3!0@1j5h3I4Q4x3X3g2U0L8$3@1`.
/
gui
/
file
/
0e9e859d22b009e869322a509c11e342
XorDDoS僵尸网络家族的某样本
https:
/
/
7cdK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6i4k6A6M7Y4g2K6N6r3!0@1j5h3I4Q4x3X3g2U0L8$3@1`.
/
gui
/
file
/
0e9e859d22b009e869322a509c11e342
$
file
-
b
0e9e859d22b009e869322a509c11e342
ELF
32
-
bit LSB executable, Intel
80386
, ..., statically linked, ...,
not
stripped
$
file
-
b
0e9e859d22b009e869322a509c11e342
ELF
32
-
bit LSB executable, Intel
80386
, ..., statically linked, ...,
not
stripped
0804CFA3
C7
44
24
08
0B
00
00
00
mov dword ptr [esp
+
8
],
0Bh
0804CFAB
C7
44
24
04
B1
2F
0B
08
mov dword ptr [esp
+
4
], offset aM7a4nqNa_0 ;
"m7A4nQ_/nA"
0804CFB3
8D
85
B3 EA FF FF lea eax, [ebp
+
var_154D]
0804CFB9
89
04
24
mov [esp], eax
0804CFBC
E8
67
B2 FF FF call dec_conf
0804CFC1
C7
44
24
08
07
00
00
00
mov dword ptr [esp
+
8
],
7
0804CFC9
C7
44
24
04
BC
2F
0B
08
mov dword ptr [esp
+
4
], offset aMN3_0 ;
"m [(n3"
0804CFD1
8D
85
B3 E9 FF FF lea eax, [ebp
+
var_164D]
0804CFD7
89
04
24
mov [esp], eax
0804CFDA
E8
49
B2 FF FF call dec_conf
0804CFA3
C7
44
24
08
0B
00
00
00
mov dword ptr [esp
+
8
],
0Bh
0804CFAB
C7
44
24
04
B1
2F
0B
08
mov dword ptr [esp
+
4
], offset aM7a4nqNa_0 ;
"m7A4nQ_/nA"
0804CFB3
8D
85
B3 EA FF FF lea eax, [ebp
+
var_154D]
0804CFB9
89
04
24
mov [esp], eax
0804CFBC
E8
67
B2 FF FF call dec_conf
0804CFC1
C7
44
24
08
07
00
00
00
mov dword ptr [esp
+
8
],
7
0804CFC9
C7
44
24
04
BC
2F
0B
08
mov dword ptr [esp
+
4
], offset aMN3_0 ;
"m [(n3"
0804CFD1
8D
85
B3 E9 FF FF lea eax, [ebp
+
var_164D]
0804CFD7
89
04
24
mov [esp], eax
0804CFDA
E8
49
B2 FF FF call dec_conf
dec_conf(v23,
"m7A4nQ_/nA"
,
11
);
dec_conf(v22,
"m [(n3"
,
7
);
dec_conf(v21,
"m6_6n3"
,
7
);
dec_conf(v19, aM4s4nacNZv,
18
);
dec_conf(v18, aMN4C,
17
);
dec_conf(v17,
"m.[$n3"
,
7
);
dec_conf(v16, a6f6,
512
);
dec_conf(v20,
"m4S4nAC/nA"
,
11
);
dec_conf(v23,
"m7A4nQ_/nA"
,
11
);
dec_conf(v22,
"m [(n3"
,
7
);
dec_conf(v21,
"m6_6n3"
,
7
);
dec_conf(v19, aM4s4nacNZv,
18
);
dec_conf(v18, aMN4C,
17
);
dec_conf(v17,
"m.[$n3"
,
7
);
dec_conf(v16, a6f6,
512
);
dec_conf(v20,
"m4S4nAC/nA"
,
11
);
08048228
dec_conf proc
08048228
55
push ebp
08048229
89
E5 mov ebp, esp
0804822B
83
EC
18
sub esp,
18h
0804822E
8B
45
10
mov eax, [ebp
+
arg_8]
08048231
89
44
24
08
mov [esp
+
8
], eax
08048235
8B
45
0C
mov eax, [ebp
+
arg_4]
08048238
89
44
24
04
mov [esp
+
4
], eax
0804823C
8B
45
08
mov eax, [ebp
+
arg_0]
0804823F
89
04
24
mov [esp], eax
08048242
E8
09
E6
01
00
call memmove
08048247
8B
45
10
mov eax, [ebp
+
arg_8]
0804824A
89
44
24
04
mov [esp
+
4
], eax
0804824E
8B
45
08
mov eax, [ebp
+
arg_0]
08048251
89
04
24
mov [esp], eax
08048254
E8
9B
11
00
00
call encrypt_code
08048259
B8
00
00
00
00
mov eax,
0
0804825E
C9 leave
0804825F
C3 retn
0804825F
dec_conf endp
08048228
dec_conf proc
08048228
55
push ebp
08048229
89
E5 mov ebp, esp
0804822B
83
EC
18
sub esp,
18h
0804822E
8B
45
10
mov eax, [ebp
+
arg_8]
08048231
89
44
24
08
mov [esp
+
8
], eax
08048235
8B
45
0C
mov eax, [ebp
+
arg_4]
08048238
89
44
24
04
mov [esp
+
4
], eax
0804823C
8B
45
08
mov eax, [ebp
+
arg_0]
0804823F
89
04
24
mov [esp], eax
08048242
E8
09
E6
01
00
call memmove
08048247
8B
45
10
mov eax, [ebp
+
arg_8]
0804824A
89
44
24
04
mov [esp
+
4
], eax
0804824E
8B
45
08
mov eax, [ebp
+
arg_0]
08048251
89
04
24
mov [esp], eax
08048254
E8
9B
11
00
00
call encrypt_code
08048259
B8
00
00
00
00
mov eax,
0
0804825E
C9 leave
0804825F
C3 retn
0804825F
dec_conf endp
int
dec_conf(char
*
dst, char
*
src,
int
size )
{
memmove( dst, src, size );
/
*
*
就地修改dst,而非返回什么
*
/
encrypt_code( dst, size );
return
0
;
}
int
dec_conf(char
*
dst, char
*
src,
int
size )
{
memmove( dst, src, size );
/
*
*
就地修改dst,而非返回什么
*
/
encrypt_code( dst, size );
return
0
;
}
/
*
*
就地修改buf
*
/
char
*
__cdecl encrypt_code(char
*
buf,
int
size)
{
char
*
p;
int
i;
p
=
buf;
for
( i
=
0
; i < size;
+
+
i )
*
p
+
+
^
=
xorkeys[i
%
16
];
return
buf;
}
/
*
*
就地修改buf
*
/
char
*
__cdecl encrypt_code(char
*
buf,
int
size)
{
char
*
p;
int
i;
p
=
buf;
for
( i
=
0
; i < size;
+
+
i )
*
p
+
+
^
=
xorkeys[i
%
16
];
return
buf;
}
080CF3E8
42
42
32
46
41
33
36
41
…xorkeys db
'BB2FA36AAA9541F0'
080CF3E8
42
42
32
46
41
33
36
41
…xorkeys db
'BB2FA36AAA9541F0'
08048C08
C7
44
24
08
0A
00
00
00
mov dword ptr [esp
+
8
],
0Ah
08048C10
C7
44
24
04
07
2D
0B
08
mov dword ptr [esp
+
4
], offset aM7a4nqNa ;
"m7A4nQ_/nA"
08048C18
8D
85
F1 FA FF FF lea eax, [ebp
+
var_50F]
08048C1E
89
04
24
mov [esp], eax
08048C21
E8
2A
DC
01
00
call memmove
08048C26
C7
44
24
04
0A
00
00
00
mov dword ptr [esp
+
4
],
0Ah
;
int
08048C2E
8D
85
F1 FA FF FF lea eax, [ebp
+
var_50F]
08048C34
89
04
24
mov [esp], eax ; char
*
08048C37
E8 B8
07
00
00
call encrypt_code
08048C08
C7
44
24
08
0A
00
00
00
mov dword ptr [esp
+
8
],
0Ah
08048C10
C7
44
24
04
07
2D
0B
08
mov dword ptr [esp
+
4
], offset aM7a4nqNa ;
"m7A4nQ_/nA"
08048C18
8D
85
F1 FA FF FF lea eax, [ebp
+
var_50F]
08048C1E
89
04
24
mov [esp], eax
08048C21
E8
2A
DC
01
00
call memmove
08048C26
C7
44
24
04
0A
00
00
00
mov dword ptr [esp
+
4
],
0Ah
;
int
08048C2E
8D
85
F1 FA FF FF lea eax, [ebp
+
var_50F]
08048C34
89
04
24
mov [esp], eax ; char
*
08048C37
E8 B8
07
00
00
call encrypt_code
0804F12F
C7
44
24
08
00
02
00
00
mov dword ptr [esp
+
8
],
200h
0804F137
C7
44
24
04
4C
32
0B
08
mov dword ptr [esp
+
4
], offset unk_80B324C
0804F13F
C7
04
24
C0
1C
0D
08
mov dword ptr [esp], offset remotestr
0804F146
E8
05
77
01
00
call memmove
0804F14B
C7
44
24
04
00
02
00
00
mov dword ptr [esp
+
4
],
200h
;
int
0804F153
C7
04
24
C0
1C
0D
08
mov dword ptr [esp], offset remotestr ; char
*
0804F15A
E8
95
A2 FF FF call encrypt_code
0804F12F
C7
44
24
08
00
02
00
00
mov dword ptr [esp
+
8
],
200h
0804F137
C7
44
24
04
4C
32
0B
08
mov dword ptr [esp
+
4
], offset unk_80B324C
0804F13F
C7
04
24
C0
1C
0D
08
mov dword ptr [esp], offset remotestr
0804F146
E8
05
77
01
00
call memmove
0804F14B
C7
44
24
04
00
02
00
00
mov dword ptr [esp
+
4
],
200h
;
int
0804F153
C7
04
24
C0
1C
0D
08
mov dword ptr [esp], offset remotestr ; char
*
0804F15A
E8
95
A2 FF FF call encrypt_code
memmove(remotestr, &unk_80B324C,
512
);
encrypt_code(remotestr,
512
);
memmove(remotestr, &unk_80B324C,
512
);
encrypt_code(remotestr,
512
);
0804D093
C7
45
CC
00
00
00
00
mov [ebp
+
var_34],
0
0804D09A
EB
26
jmp short loc_804D0C2
0804D09C
0804D09C
loc_804D09C:
0804D09C
8B
55
CC mov edx, [ebp
+
var_34]
0804D09F
89
D0 mov eax, edx
0804D0A1
C1 E0
02
shl eax,
2
0804D0A4
01
D0 add eax, edx
0804D0A6
C1 E0
02
shl eax,
2
/
*
*
daemonname位于.data,而非.rodata
*
/
0804D0A9
05
20
F1
0C
08
add eax, offset daemonname ;
"!#Ff3VE.-7"
0804D0AE
C7
44
24
04
14
00
00
00
mov dword ptr [esp
+
4
],
14h
;
int
0804D0B6
89
04
24
mov [esp], eax ; char
*
0804D0B9
E8
36
C3 FF FF call encrypt_code
0804D0BE
83
45
CC
01
add [ebp
+
var_34],
1
0804D0C2
0804D0C2
loc_804D0C2:
0804D0C2
83
7D
CC
16
cmp
[ebp
+
var_34],
16h
0804D0C6
76
D4 jbe short loc_804D09C
0804D093
C7
45
CC
00
00
00
00
mov [ebp
+
var_34],
0
0804D09A
EB
26
jmp short loc_804D0C2
0804D09C
0804D09C
loc_804D09C:
0804D09C
8B
55
CC mov edx, [ebp
+
var_34]
0804D09F
89
D0 mov eax, edx
0804D0A1
C1 E0
02
shl eax,
2
0804D0A4
01
D0 add eax, edx
0804D0A6
C1 E0
02
shl eax,
2
/
*
*
daemonname位于.data,而非.rodata
*
/
0804D0A9
05
20
F1
0C
08
add eax, offset daemonname ;
"!#Ff3VE.-7"
0804D0AE
C7
44
24
04
14
00
00
00
mov dword ptr [esp
+
4
],
14h
;
int
0804D0B6
89
04
24
mov [esp], eax ; char
*
0804D0B9
E8
36
C3 FF FF call encrypt_code
0804D0BE
83
45
CC
01
add [ebp
+
var_34],
1
0804D0C2
0804D0C2
loc_804D0C2:
0804D0C2
83
7D
CC
16
cmp
[ebp
+
var_34],
16h
0804D0C6
76
D4 jbe short loc_804D09C
for
( i
=
0
; i <
=
22
;
+
+
i )
encrypt_code(&daemonname[
20
*
i],
20
);
for
( i
=
0
; i <
=
22
;
+
+
i )
encrypt_code(&daemonname[
20
*
i],
20
);
《Angr符号执行练习
-
-
SecuInside
2016
mbrainfuzz》
https:
/
/
scz.
617.cn
/
unix
/
202503311347.txt
《Angr符号执行练习
-
-
SecuInside
2016
mbrainfuzz》
https:
/
/
scz.
617.cn
/
unix
/
202503311347.txt
def
get_func_info ( r2, func ) :
cmd
=
f
"afij sym.{func}"
info
=
r2.cmd( cmd )
info
=
json.loads( info )
info
=
info[
0
]
func_entry
=
info[
'offset'
]
func_exit
=
info[
'offset'
]
+
info[
'size'
]
-
1
return
( func_entry, func_exit )
def
get_func_info ( r2, func ) :
cmd
=
f
"afij sym.{func}"
info
=
r2.cmd( cmd )
info
=
json.loads( info )
info
=
info[
0
]
func_entry
=
info[
'offset'
]
func_exit
=
info[
'offset'
]
+
info[
'size'
]
-
1
return
( func_entry, func_exit )
def
find_xrefs_to_func ( r2, func ) :
xrefs
=
[]
cmd
=
f
"axtj sym.{func}"
info
=
r2.cmd( cmd )
info
=
json.loads( info )
for
item
in
info :
xrefs.append( item[
'from'
] )
return
xrefs
def
find_xrefs_to_func ( r2, func ) :
xrefs
=
[]
cmd
=
f
"axtj sym.{func}"
info
=
r2.cmd( cmd )
info
=
json.loads( info )
for
item
in
info :
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课