-
-
[原创]hutrace工具系列第3篇之Linux应用
-
发表于: 2022-6-6 19:58 10708
-
目录
1、hutrace工具系列第1篇之基本功能介绍
2、hutrace工具系列第2篇之Windows应用
3、hutrace工具系列第3篇之Linux应用
4、hutrace工具系列第4篇之衍生工具hzytrace
Linux上常用程序记录工具有strace、ltrace等,能够记录到程序的系统调用以及API函数调用信息,但是均无法得到进一步的调用位置等,hutrace则同时利用dynamorio实现了基本块以及指令状态等的记录,功能与Windows平台保持一致,本文仅对与win有差异的部分进行简单介绍,且Linux平台能公开的样例较少,内容偏少一点。
Linux下的hutrace使用与Windows基本一致:
拿一个最简单的例子来演示,一个比较老的ctf的最简单题,flag解密后直接比较,不过其中夹杂了一些main函数等位置cc断点的检测:
查看trace得到的API记录:
当然ltrace也可以做到哦~只是hutrace得到的信息更为丰富。
Linux下进程创建方式比较多样,而Fork又有别于常规的进程创建方式,导致hutrace需要额外处理Linux上常见的Fork进程的记录问题,当然处理难度不大,来看下最简单的演示程序:
开工:
我们只看下子进程的记录日志:
常规方式的进程创建没啥特别的,不再说了,可惜Linux上dynamorio不支持Windows上的-syswide_on功能。
上一篇中介绍的windows系统调用使用常见相对小众,Linux下就比较常见了,hutrace在linux系统上同样默认不记录syscall调用信息,而且不在hutrace.config中设置参数信息的话只打印系统调用名称,只有设置了参数信息才会打印系统调用的参数,实际使用时和打印API函数以及上一篇Window应用中介绍的使用方式类似,在hutrace.config配置文件中添加对应syscall的参数信息:
得到的部分日志记录:
仅这一部分可打印16进制数据的功能就比strace打印的更友好点了~而且strace本身基于ptrace实现的,遇到基于ptrace实现的一些反调试技术就无法继续追踪了:
对比hutrace的结果:
不过目前还是存在一些基于ptrace的反调试技术如debugblocker等可能导致hutrace追踪失败的,可以只使用hutrace追踪父进程,提取其处理流程对程序进行patch等,后面如果有想到好点的解决方案也会添加进去。
Linux系统上相比Window上利用hutrace加载自定义插件的限制更大,无法像Win上方便的利用GetModuleHandle获取除kernel32.dll、kernerbase.dll模块外其它模块的基址(上一篇提到过,当然dynamorio自己也有接口),虽然还有其它方法可以实现,但是目前想到的代价略微有点大,暂时也没有需求,后面如果有好的实现方法会更新下,暂时只支持固定地址方式进行Hook(不支持windows平台上hutrace插件的模块名+偏移的方式),下面来看一个演示例子,在hutrace.config中添加下述配置:
目标程序0x400706为一个简单的打印参数函数:
对应的Hook函数实现(my_fprintf函数指针由hutrace插件自动赋值,不用考虑其实现),通过hook方式将所有的参数设置为1:
同样可以不依赖my_getarg、my_setarg等插件模板中已经实现好的函数对寄存器等进行修改(利用mc参数)~
Windows上的调试分析工具很多且均比较完善了,Linux上gdb调试一些多进程程序都稍微麻烦点,另外稍微特殊的程序如利用错误section头部反调试的,虽然也可以gdb附加,但是使用hutrace来搞都没啥问题,特殊情况下hutrace无法运行的程序就要靠接下来介绍的hzytrace了,详见下一页基于pin实现的hzytrace具体介绍(https://bbs.pediy.com/thread-273188.htm)。
github地址:https://github.com/huhu0706/hutrace
# huhu @ huhu in ~/Desktop/my/build/bin64 [9:58:27] C:127
$ .
/
hutrace
ERROR: Usage error:
Usage:
-
logdir [ .] Log directory to
print
library call data
-
only_from_app [ false] Reports only library calls
from
the app
-
trace_to_librarys [ ""] Trace specify librarys
-
record_start_addr [ ""] record begin at start_addr
-
record_end_addr [ ""] record finished at end_addr
-
follow_children [ false] Trace child processes
-
print_ret_addr [ false]
Print
library call's
return
address
-
print_ins_info [ false]
Print
instructions disassemble info
-
print_ins_reg [ false]
Print
instructions disassemble reg
-
print_ins_all [ false]
Print
instructions trace info
-
print_syscall [ false]
Print
syscall info
-
num_unknown_args [
2
] Number of unknown libcall args to
print
-
num_max_args [
6
] Maximum number of arguments to
print
-
config [ ""] The path to custom config
file
.
-
ignore_underscore [ false] Ignores library routine names starting with
"_"
.
-
only_to_lib [ ""] Only reports calls to the library <lib_name>.
-
help
[ false]
Print
this message.
-
version [ false]
Print
version number.
-
verbose [
1
] Change verbosity.
-
use_config [ true] Use config
file
# huhu @ huhu in ~/Desktop/my/build/bin64 [9:58:27] C:127
$ .
/
hutrace
ERROR: Usage error:
Usage:
-
logdir [ .] Log directory to
print
library call data
-
only_from_app [ false] Reports only library calls
from
the app
-
trace_to_librarys [ ""] Trace specify librarys
-
record_start_addr [ ""] record begin at start_addr
-
record_end_addr [ ""] record finished at end_addr
-
follow_children [ false] Trace child processes
-
print_ret_addr [ false]
Print
library call's
return
address
-
print_ins_info [ false]
Print
instructions disassemble info
-
print_ins_reg [ false]
Print
instructions disassemble reg
-
print_ins_all [ false]
Print
instructions trace info
-
print_syscall [ false]
Print
syscall info
-
num_unknown_args [
2
] Number of unknown libcall args to
print
-
num_max_args [
6
] Maximum number of arguments to
print
-
config [ ""] The path to custom config
file
.
-
ignore_underscore [ false] Ignores library routine names starting with
"_"
.
-
only_to_lib [ ""] Only reports calls to the library <lib_name>.
-
help
[ false]
Print
this message.
-
version [ false]
Print
version number.
-
verbose [
1
] Change verbosity.
-
use_config [ true] Use config
file
$ .
/
hutrace
-
only_from_app
-
print_ret_addr
-
print_ins_info
-
-
.
/
noccbytes
$ .
/
hutrace
-
only_from_app
-
print_ret_addr
-
print_ins_info
-
-
.
/
noccbytes
C7ffff3d8dbb7|
7ffff3d8d8a0
7ffff3d8d8a0
:
jmp <rel> qword ptr [
0x00007ffff3f8ef98
]
J7ffff3d8d8a0|
7ffff6829a50
~~
5820
~~ libc.so.
6
!strcpy N:
0x42
arg
1
: WattoSays
(
type
=
char
*
, size
=
0x0
)
and
return
to module
id
:
4
, retraddr:
0x7ffff3d8dbbc
,offset:
0xbbc
7ffff3d8dbbc
:
lea rdx, [rbp
-
0x30
]
mov rax, qword ptr [rbp
-
0x38
]
mov rsi, rdx
mov rdi, rax
call
0x00007ffff3d8d8d0
and
strcpy
return
value:
0x7fffffffda20
arg
0
: WattoSays
(
type
=
char
*
, size
=
0x0
)
C7ffff3d8dbca|
7ffff3d8d8d0
7ffff3d8d8d0
:
jmp <rel> qword ptr [
0x00007ffff3f8efb0
]
J7ffff3d8d8d0|
7ffff68235f0
~~
5820
~~ libc.so.
6
!strcmp N:
0x43
<
-
-
-
-
最终解密的password在此比较
arg
0
:
1234567890
(
type
=
char
*
, size
=
0x0
)
arg
1
: WattoSays
(
type
=
char
*
, size
=
0x0
)
and
return
to module
id
:
4
, retraddr:
0x7ffff3d8dbcf
,offset:
0xbcf
7ffff3d8dbcf
:
test eax, eax
jnz
0x00007ffff3d8dbda
and
strcmp
return
value:
0xffffffda
7ffff3d8dbda
:
lea rdi, <rel> [
0x00007ffff3d8de19
]
call
0x00007ffff3d8d8f0
C7ffff3d8dbe1|
7ffff3d8d8f0
J7ffff3d8d8f0|
7ffff67f36a0
~~
5820
~~ libc.so.
6
!puts N:
0x44
arg
0
:
Wrong Password (
type
=
char
*
, size
=
0x0
)
and
return
to module
id
:
4
, retraddr:
0x7ffff3d8dbe6
,offset:
0xbe6
C7ffff3d8dbb7|
7ffff3d8d8a0
7ffff3d8d8a0
:
jmp <rel> qword ptr [
0x00007ffff3f8ef98
]
J7ffff3d8d8a0|
7ffff6829a50
~~
5820
~~ libc.so.
6
!strcpy N:
0x42
arg
1
: WattoSays
(
type
=
char
*
, size
=
0x0
)
and
return
to module
id
:
4
, retraddr:
0x7ffff3d8dbbc
,offset:
0xbbc
7ffff3d8dbbc
:
lea rdx, [rbp
-
0x30
]
mov rax, qword ptr [rbp
-
0x38
]
mov rsi, rdx
mov rdi, rax
call
0x00007ffff3d8d8d0
and
strcpy
return
value:
0x7fffffffda20
arg
0
: WattoSays
(
type
=
char
*
, size
=
0x0
)
C7ffff3d8dbca|
7ffff3d8d8d0
7ffff3d8d8d0
:
jmp <rel> qword ptr [
0x00007ffff3f8efb0
]
J7ffff3d8d8d0|
7ffff68235f0
~~
5820
~~ libc.so.
6
!strcmp N:
0x43
<
-
-
-
-
最终解密的password在此比较
arg
0
:
1234567890
(
type
=
char
*
, size
=
0x0
)
arg
1
: WattoSays
(
type
=
char
*
, size
=
0x0
)
and
return
to module
id
:
4
, retraddr:
0x7ffff3d8dbcf
,offset:
0xbcf
7ffff3d8dbcf
:
test eax, eax
jnz
0x00007ffff3d8dbda
and
strcmp
return
value:
0xffffffda
7ffff3d8dbda
:
lea rdi, <rel> [
0x00007ffff3d8de19
]
call
0x00007ffff3d8d8f0
C7ffff3d8dbe1|
7ffff3d8d8f0
J7ffff3d8d8f0|
7ffff67f36a0
~~
5820
~~ libc.so.
6
!puts N:
0x44
arg
0
:
Wrong Password (
type
=
char
*
, size
=
0x0
)
and
return
to module
id
:
4
, retraddr:
0x7ffff3d8dbe6
,offset:
0xbe6
result
=
fork();
if
(result
=
=
-
1
)
{
printf(
"Fork error\n"
);
}
else
if
(result
=
=
0
)
{
printf(
"The returned value is %d In child process!! My PID is %d\n"
,result,getpid());
}
else
{
printf(
"The returned value is %d In father process!! My PID is %d\n"
,result,getpid());
}
result
=
fork();
if
(result
=
=
-
1
)
{
printf(
"Fork error\n"
);
}
else
if
(result
=
=
0
)
{
printf(
"The returned value is %d In child process!! My PID is %d\n"
,result,getpid());
}
else
{
printf(
"The returned value is %d In father process!! My PID is %d\n"
,result,getpid());
}
$ .
/
hutrace
-
only_from_app
-
print_ret_addr
-
print_ins_info
-
-
.
/
myproctest.out
The returned value
is
7774
In father process!! My PID
is
7773
The returned value
is
0
In child process!! My PID
is
7774
$ .
/
hutrace
-
only_from_app
-
print_ret_addr
-
print_ins_info
-
-
.
/
myproctest.out
The returned value
is
7774
In father process!! My PID
is
7773
The returned value
is
0
In child process!! My PID
is
7774
hutrace.config文件中设置:
int
|syscall_read|
LONG
|__out
hex
^ARG2|
int
int
|syscall_write|
LONG
|char
*
int
|syscall_open|char
*
|
LONG
运行hutrace记录ls程序运行的syscall:
# huhu @ huhu in ~/Desktop/my/build/bin64 [8:17:52]
$ .
/
hutrace
-
only_from_app
-
print_ret_addr
-
print_syscall
-
-
/
bin
/
ls
-
al
hutrace.config文件中设置:
int
|syscall_read|
LONG
|__out
hex
^ARG2|
int
int
|syscall_write|
LONG
|char
*
int
|syscall_open|char
*
|
LONG