什么是lldb
lldb是llvm+clang工具链中的调试器,类似于gdb等,提供的可用命令和设计架构跟gdb略有不同。
一些反调试手段
下面罗列的一些反调试手段均在OS X系统上编写的控制台程序中测试通过。(ios程序上不保证可用)
严格划分的话,反调试实际上分为两种类型:检测和防治
检测类型的给你提供检测到调试器后的处理机会。
防止类型的在发现调试状态时会直接终止程序。
以下的示例不严格区分。
1.
1
2
3
4
5
6
7
8
9
10
11
|
#include
#include
#include
#include
int
main() {
struct
winsize win;
puts
((isatty (1) && !ioctl (1, TIOCGWINSZ, &win) && !win.ws_col)?
"traced by lldb"
: “not traced by lldb");
return
0;
}
|
2.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#include
#include
void
handler(
int
signo)
{
printf
(“not traced by lldb\n");
}
int
main(
int
argc,
const
char
* argv[])
{
signal
(SIGTRAP,handler);
__asm__(
"int3"
);
printf
(
"traced by lldb\n"
);
return
0;
}
|
3.
1
2
3
4
5
6
7
8
9
10
|
#include
#include
#include
int
main()
{
ptrace(31, 0, 0, 0);
printf
(“normal\n");
return
0;
}
|
4.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#include
#include
static
int
check_debugger( ) __attribute__((always_inline));
int
check_debugger( )
{
size_t
size =
sizeof
(
struct
kinfo_proc);
struct
kinfo_proc info;
int
ret,name[4];
memset
(&info, 0,
sizeof
(
struct
kinfo_proc));
name[0] = CTL_KERN;
name[1] = KERN_PROC;
name[2] = KERN_PROC_PID;
name[3] = getpid();
if
((ret = (sysctl(name, 4, &info, &size, NULL, 0)))){
return
ret;
//sysctl() failed for some reason
}
return
(info.kp_proc.p_flag & P_TRACED) ? 1 : 0;
}
|
5.
1
2
3
4
5
6
7
8
9
|
static
void
stop_debugger_running(
void
)
{
system
(
"killall lldb"
);
}
void
main() {
stop_debugger_running();
printf
(“normal\n”);
}
|
6.
1
2
3
4
5
6
7
8
9
|
#include
#include
void
main() {
if
(ptrace(0, 0, NULL, 0) == -1)
printf
("traced by lldb”);
else
printf
(“not traced by lldb”);
}
|
7.
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
|
#include
#include
#include
#include
#include
#include
static
int
debugger_attached(
void
)
{
int
pid;
int
from_child[2] = {-1, -1};
if
(pipe(from_child) < 0) {
return
-1;
}
pid = fork();
if
(pid == -1) {
return
-1;
}
if
(pid == 0) {
uint8_t ret = 0;
int
ppid = getppid();
close(from_child[0]);
if
(ptrace(PTRACE_ATTACH, ppid, NULL, NULL) == 0) {
waitpid(ppid, NULL, 0);
write(from_child[1], &ret,
sizeof
(ret));
ptrace(PTRACE_DETACH, ppid, NULL, NULL);
exit
(0);
}
ret = 1;
write(from_child[1], &ret,
sizeof
(ret));
exit
(0);
}
else
{
uint8_t ret = -1;
while
((read(from_child[0], &ret,
sizeof
(ret)) < 0)
&& (
errno
== EINTR));
if
(ret < 0) {
}
close(from_child[1]);
close(from_child[0]);
waitpid(pid, NULL, 0);
return
ret;
}
}
|