这题也是比较经典首先
static void sigtrap_handler(int signum)
{
debugger_present = 0;
signal(sub_1(), sub_2());
}
通过sub_1函数返回值信号来判断,自身是否被跟踪。注册该信号的处理函数,然后主动触发该信号,如果可以收到该信号,说明没有被跟踪调试。
正常想法就是patch这个函数就能绕过反调试,但是这恰好中了计,为什么这里用函数返回值作为参数肯定是有意义的。然后是线程判断并关闭了标准输出。
if ( fork() )
{ wait(0LL);
sleep(4u);}
else {
puts("give you a shell! now you need to get flag!");
fclose(stdout);
read(0, buf, 0x12uLL);
sub_3(buf); }
wait()父进程调用,返回子进程状态的变化(由运行到结束)
当父进程调用wait()将会阻塞,直到子进程状态发生变化
wait返回子子进程的pid,如果没有子进程,则返回-1
wait需要整型指针参数,记录子进程退出的状态
要绕过这个线程判断的话就得system(`echo $0`)启动一个shell,然后绕过关闭输出流可以把标准输出重定向到标准输入,使用exec 1>&0即可,最后只需要布局
signal(sub_1(), sub_2())
sub_1()返回31
sub_2()劫持成onegadget
之后控制rax导致系统调用异常触发信号机制并且触发反调试代码就能拿到shell
信号编号 |
名称默认动作说明 |
1 |
SIGHUP 终止终止控制终端或进程 |
2 |
SIGINT 终止由键盘引起的终端(Ctrl-c) |
3 |
SIGQUIT dump 控制终端发送给进程的信号, 键盘产生的退出(Ctrl-), |
4 |
GIGILL dusmp 非法指令引起 |
5 |
SIGTRAP dump debug中断 |
6 |
SIGABRT/SIGIOT dump 异常中止 |
7 |
SIGBUS/SIGEMT dump 总线异常/EMT指令 |
8 |
SIGFPE dump 浮点运算溢出 |
9 |
SIGKILL 终止强制杀死进程(大招, 进程不可捕获) |
10 |
SIGUSR1 终止用户信号, 进程可自定义用途 |
11 |
SIGSEGV dump 非法内存地址引起 |
12 |
SIGUSR2 终止用户信号, 进程可自定义用途 |
13 |
SIGPIPE 终止向某个没有读取的管道中写入数据 |
14 |
SIGALRM 终止时钟中断(闹钟) |
15 |
SIGTERM 终止进程终止(进程可捕获) |
16 |
SIGSTKFLT 终止协处理器栈错误 |
17 |
SIGCHLD 忽略子进程退出或中断 |
18 |
SIGCONT 继续如进程停止状态则开始运行 |
19 |
SIGSTOP 停止停止进程运行 |
20 |
SIGSTP 停止键盘产生的停止 |
21 |
SIGTTIN 停止后台进程请求输入 |
22 |
SIGTTOU 停止后台进程请求输出 |
23 |
SIGURG 忽略 socket发送紧急情况 |
24 |
SIGXCPU dump CPU时间限制被打破 |
25 |
SIGXFSZ dump 文件大小限制被打破 |
26 |
SIGVTALRM 终止虚拟定时时钟 |
27 |
SIGPROF 终止 profile timer clock |
28 |
SIGWINCH 忽略窗口尺寸调整 |
29 |
SIGIO/SIGPOLL 终止 I/O可用 |
30 |
SIGPWR 终止电源异常 |
31 |
SIGSYS/SYSUNUSED dump 系统调用异常 |
原文始发于微信公众号(由由学习吧):国际赛反调试加多线程获得shell
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论