-
-
[原创]hutrace工具系列第4篇之衍生工具hzytrace
-
发表于: 2022-6-6 19:59 11304
-
目录
1、hutrace工具系列第1篇之基本功能介绍
2、hutrace工具系列第2篇之Windows应用
3、hutrace工具系列第3篇之Linux应用
4、hutrace工具系列第4篇之衍生工具hzytrace
<p> hutrace的功能已经实现的比较全面了,dynamroio与pin虽然在对程序的分析处理上各有一定的优势,但是实际中测试下来dynamorio在Linux下的兼容性要比pin稍微差一点,存在一些无法用hutrace记录但pin可以追踪的情况,而且pin提供的接口功能也更丰富,故基于pin完成了大部分hutrace的功能,也即是下面要介绍的hzytrace工具。hzytrace目前仅支持linux平台,windows平台上基于dynamrio的hutrace在效率、兼容性上均优于pin,暂时就还没完善window下的hzytrace。
hzytrace本身基于pin+codapintracer开发,原codapintracer仅支持Windows平台的API记录(类似drltrace),代码基于Window做了特别多的处理(所以hzytrace移植到win上比较简单...),功能也很多,导致移植到linux多了很多坑,而且在linux下pin的对程序的处理接口也存在一些问题,最终魔改完的代码快没法看了。。不过整体来说hzytrace的功能性还可以,可作为hutrace在处理一些Linux程序上的补充,本篇先介绍下hzytrace的基本功能,最后将结合一些实例进行演示。
hzytrace支持的基本功能参数如下:
默认情况下,hzytrace会记录程序的API调用、Syscall调用以及所有的基本块转移记录,下面结合一些实例的记录信息进行介绍。
在hzytrace目录中执行下述指令:
查看Results目录下记录的trace日志内容:
显示功能基本与hutrace保持一致,同时支持hex以及struct打印,除后面介绍的hook、dump功能上(不支持hutrace的简易patch、hide功能),hzytrace_linux.config与hutrace.config在API参数打印上的设置基本一致。
如果不需要打印基本块对应的汇编指令,可以设置bbllog参数的值为false:
trace结果:
注意开启bbllog的trace日志中会打印出所有ls主程序中执行的代码,而在上述不开启bbllog的trace日志结果中,并不会记录到跳转到main函数0x402A00地址的信息,因为并非是从ls主程序中执行的指令跳转进入的main函数。
功能及使用方式与hutrace类似,默认情况下只打印执行的syscall的名称,在hzytrace_linux.config文件中设置参数信息后才会根据参数类型打印对应的参数:
trace记录样例(运行过程中所有syscall):
分析trace的结果:
如果不需要记录syscall调用,同样设置syscall参数为0即可:
功能类似hutrace,开启指令状态记录时则不需要再记录bbllog功能中的指令反汇编结果:
trace的部分日志结果:
指定需要trace的指令范围,需要设置为基本块的开始或结束地址(为了便于展示,可以取消全局的syscall调用打印):
trace的结果信息中只会打印到0x402c7c的前一个基本块信息结束,并不会打印0x402c7c所在基本块的指令信息等。
利用target参数指定需要trace的模块:
trace得到的部分结果:
这里继续使用hutrace的linux应用文章中的例子进行演示,将原本程序中打印函数的参数从1-8修改为11-18,首先在hzytrace_linux.config设置需要hook的地址:
在hzytrace中简化了插件的加载和调用方式,只需要设置需要hook的的地址即可,而且不支持hutrace提供的函数开始、结束同时hook,如果有类似需求,可以在返回地址处添加新的返回地址hook条目,hzytrace运行到0x400706地址处时会加载mypinplugin.so并调用导出函数名为f_hookpre_0x400706的导出函数。
mypinplugin.so编译时可以使用以下编译选项:
同时注意因为pin的限制,插件中无法引用其它系统的libc.so文件,故不建议在hook函数中引用api函数实现较为复杂的功能,如果确有此类需求,可以尝试编译成静态的so文件或者编译一个main函数为空、仅导出功能函数的pin插件加载,使用hutrace则不受此限制。
根据hzytrace在运行时输出的调试信息中测试程序soTest加载后的代码范围0x400000-400b43,来演示下hzytrace的内存dump功能,在hzytrace_linux.config设置需要dump的时机以及需要dump的内存地址以及内存大小。
同样设置代码运行到0x400706时dump地址从0x400000开始大小为0xb43字节的内存数据,运行测试程序后,在Result目录中对应的日志记录文件夹中生成内存dump文件。
dump功能可以和hook功能指定同一个地址,即可执行到该地址后进行dump操作,又可以在当前地址处使用hook功能加载插件(hutrace则不支持)。
dump功能同样可以在不同运行地址状态指定相同地址范围的内存进行提取,dump的文件名结尾会进行累加,可以比对不同状态下内存状态信息改变情况。
来看一个几年前qwb里ling博狗的例子“hide”,用了upx壳并且修改了一些upx标识,无法自动脱壳,程序本身使用了ptrace的PTRACE_TRACEME反调试(使用strace跟踪会退出),而且本身程序使用syscall完成读写、还使用了一处虚假的flag校验函数进行混淆,常规方式可以使用“catch syscall ptrace”逐步定位关键代码处,下面我们尝试使用hzytrace处理类似程序(hutrace虽然可以正常处理upx和PTRACE_TRACEME,但是这个程序无法正常trace,原因没有深入研究)。
查看日志直接搜索输入的“1234567890”(trace的日志500m文件使用010edit秒搜):
因为hzytrace仅对运行的代码进行记录,下面把这段内存进行dump拖进ida里查看完整的代码逻辑,在hzytrace_linux.config中设置执行到0x4c8eeb代码处时自动dump地址为0x400000代码处的内存(可设置关闭aslr固定内存地址):
再次运行在对应的result日志目录生成内存dump文件,拖进ida,查看上述记录的日志中对应代码:
后面分析算法既可以ida静态,也可使用hzytrace的inslog参数追踪代码执行过程的寄存器及内存信息辅助分析算法,亦可使用gdb根据日志中的ptrace调用信息对其反调试进行绕过并继续调试,不再赘述。
这个程序来自某次分享的ctf赛题,使用双进程方式进行反调试,但是没有使用特别复杂的debugblock方式,所以依旧可以使用hzytrace进行指令流的trace(bbllog功能),但是无法使用inslog功能,全指令插桩会影响其执行流程:
同样可以在trace的日志中直接搜索到使用syscall方式读取输入的测试flag的代码位置:
在hzytrace_linux.config中设置dump内存(关闭aslr的情况下,查看0x7fffe42f6360代码所在内存范围,确保内存地址固定):
后续可以据此静态分析,同样也可以向上述hide一样对照trace日志中父进程对子进程的操作进行针对性的处理,只是不能支持inslog功能打印寄存器及引用的内存状态了,父进程的处理代码地址可简单定位如下:
实际上像一些更复杂的debugblock代码等使用hzytrace处理子进程时也会崩溃,有的情况下可以通过pin提供的接口对其进行绕过,但是代价略大点,同样后续有好的方案了会进行更新。
前面的文章中提到hzytrace一个主要目的是为了应对linux平台下一些程序无法使用hutrace处理的问题,当然不止是上面提到的一些小众的ctf赛题,pin的接口相对更为丰富,hzytrace也只是相对hutrace稍微简化了下,功能整体来说保持一致。
github地址:https://github.com/huhu0706/hzytrace
-
bbllog [default true] 打印所有执行基本块的汇编指令
-
forklog [default true] 默认追踪fork的子进程
-
syscall [default true] 默认追踪进程的syscall调用
-
inslog [default false] 打印所有执行指令的运行状态信息
-
logstart [default false] 指定记录的指令开始地址
-
logend [default false] 指定记录的指令结束地址
-
target [default
-
] 指定需要记录的模块名
-
allimage [default false] 记录所有模块的运行
-
bbllog [default true] 打印所有执行基本块的汇编指令
-
forklog [default true] 默认追踪fork的子进程
-
syscall [default true] 默认追踪进程的syscall调用
-
inslog [default false] 打印所有执行指令的运行状态信息
-
logstart [default false] 指定记录的指令开始地址
-
logend [default false] 指定记录的指令结束地址
-
target [default
-
] 指定需要记录的模块名
-
allimage [default false] 记录所有模块的运行
# huhu @ huhu in ~/Desktop/pin-3.5 [3:12:07]
$ .
/
pin
-
t hzytrace.so
-
bbllog
-
-
ls
-
al
[INFO] Configuring Pintool
[INFO] Starting instrumented program
Load Image:
/
bin
/
ls Base:
400000
-
41da63
setMainIMGAddress:
400000
41da63
Load Image:
/
lib64
/
ld
-
linux
-
x86
-
64.so
.
2
Base:
7f8438bd4000
-
7f8438bf93af
Load Image:[vdso] Base:
7ffdde88b000
-
7ffdde88c02a
[INFO] Opening
file
.
/
Results
/
2022_05_21_03_07_08
/
/
TRACER
/
hzytrace.ls.
11596.0
.
1653120428.out
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libselinux.so.
1
Base:
7f84252b9000
-
7f84254da6df
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libc.so.
6
Base:
7f8424ec2000
-
7f842528b99f
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libpcre.so.
3
Base:
7f8424c4b000
-
7f8424eba107
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libdl.so.
2
Base:
7f8424a2f000
-
7f8424c320ef
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libpthread.so.
0
Base:
7f8424811000
-
7f8424a2d427
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libnss_compat.so.
2
Base:
7f8423474000
-
7f842367c45f
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libnsl.so.
1
Base:
7f8423256000
-
7f842346ea57
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libnss_nis.so.
2
Base:
7f8422f82000
-
7f842318d587
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libnss_files.so.
2
Base:
7f8422d6b000
-
7f8422f7c717
/
/
以上为hzytrace打印的调试信息
total
6228
drwxr
-
x
-
-
-
4
huhu huhu
4096
May
21
03
:
07
.
drwxr
-
x
-
-
-
48
huhu huhu
4096
May
21
02
:
50
..
/
/
省略部分ls结果显示
# huhu @ huhu in ~/Desktop/pin-3.5 [3:12:07]
$ .
/
pin
-
t hzytrace.so
-
bbllog
-
-
ls
-
al
[INFO] Configuring Pintool
[INFO] Starting instrumented program
Load Image:
/
bin
/
ls Base:
400000
-
41da63
setMainIMGAddress:
400000
41da63
Load Image:
/
lib64
/
ld
-
linux
-
x86
-
64.so
.
2
Base:
7f8438bd4000
-
7f8438bf93af
Load Image:[vdso] Base:
7ffdde88b000
-
7ffdde88c02a
[INFO] Opening
file
.
/
Results
/
2022_05_21_03_07_08
/
/
TRACER
/
hzytrace.ls.
11596.0
.
1653120428.out
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libselinux.so.
1
Base:
7f84252b9000
-
7f84254da6df
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libc.so.
6
Base:
7f8424ec2000
-
7f842528b99f
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libpcre.so.
3
Base:
7f8424c4b000
-
7f8424eba107
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libdl.so.
2
Base:
7f8424a2f000
-
7f8424c320ef
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libpthread.so.
0
Base:
7f8424811000
-
7f8424a2d427
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libnss_compat.so.
2
Base:
7f8423474000
-
7f842367c45f
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libnsl.so.
1
Base:
7f8423256000
-
7f842346ea57
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libnss_nis.so.
2
Base:
7f8422f82000
-
7f842318d587
Load Image:
/
lib
/
x86_64
-
linux
-
gnu
/
libnss_files.so.
2
Base:
7f8422d6b000
-
7f8422f7c717
/
/
以上为hzytrace打印的调试信息
total
6228
drwxr
-
x
-
-
-
4
huhu huhu
4096
May
21
03
:
07
.
drwxr
-
x
-
-
-
48
huhu huhu
4096
May
21
02
:
50
..
/
/
省略部分ls结果显示
C0x4049c4|
0x402640
/
/
C0x4049c4对应下面ida中ls程序反汇编结果
/
/
.text:
00000000004049AF
mov r8, offset fini ; fini
/
/
.text:
00000000004049B6
mov rcx, offset init ; init
/
/
.text:
00000000004049BD
mov rdi, offset main ; main
/
/
.text:
00000000004049C4
call ___libc_start_main
B0x402640|
0x402640
D0x402640|jmp qword ptr [rip
+
0x21bb7a
]
B0x402646|
0x40264b
D0x402646|push
0x35
D0x40264b|jmp
0x4022e0
B0x4022e0|
0x4022e6
D0x4022e0|push qword ptr [rip
+
0x21bd22
]
D0x4022e6|jmp qword ptr [rip
+
0x21bd24
]
J0x4022e6|
0x7f15489d0f10
/
/
hzytrace_linux.config未配置的函数默认打印四个参数
~~
16451
~~ libc.so.
6
!__libc_start_main N:
0x1
arg
0
:
0x402a00
arg
1
:
0x2
arg
2
:
0x7ffda586d668
arg
3
:
0x413bb0
/
/
ls的init
B0x413bb0|
0x413bdc
D0x413bb0|push r15
D0x413bb2|push r14
D0x413bb4|mov r15d, edi
D0x413bb7|push r13
D0x413bb9|push r12
D0x413bbb|lea r12, ptr [rip
+
0x20a23e
]
D0x413bc2|push rbp
D0x413bc3|lea rbp, ptr [rip
+
0x20a23e
]
D0x413bca|push rbx
D0x413bcb|mov r14, rsi
D0x413bce|mov r13, rdx
D0x413bd1|sub rbp, r12
D0x413bd4|sub rsp,
0x8
D0x413bd8|sar rbp,
0x3
D0x413bdc|call
0x4022b8
C0x413bdc|
0x4022b8
......
/
/
hzytrace_linux.config配置的函数根据设置的参数类型的打印参数信息
~~
16451
~~ libc.so.
6
!__lxstat N:
0x25b
arg
0
:
0x1
arg
1
:
0x7ffda586ce00
arg
2
:
0x246d3e0
arg
3
:
0x2
~~
16451
~~ libc.so.
6
!__lxstat64 N:
0x25c
arg
0
:
0x1
(
type
=
int
, size
=
0x4
)
arg
1
: pintool.log (
type
=
char
*
, size
=
0x0
)
arg
2
: (
type
=
char
*
, size
=
0x0
)
S|lstat:
6
executed libc.so.
6
!__lxstat returnIp:
0x4080c9
=
>
retval:
0x0
executed libc.so.
6
!__lxstat64 returnIp:
0x4080c9
=
>
retval:
0x0
(
type
=
int
, size
=
0x4
)
......
C0x4049c4|
0x402640
/
/
C0x4049c4对应下面ida中ls程序反汇编结果
/
/
.text:
00000000004049AF
mov r8, offset fini ; fini
/
/
.text:
00000000004049B6
mov rcx, offset init ; init
/
/
.text:
00000000004049BD
mov rdi, offset main ; main
/
/
.text:
00000000004049C4
call ___libc_start_main
B0x402640|
0x402640
D0x402640|jmp qword ptr [rip
+
0x21bb7a
]
B0x402646|
0x40264b
D0x402646|push
0x35
D0x40264b|jmp
0x4022e0
B0x4022e0|
0x4022e6
D0x4022e0|push qword ptr [rip
+
0x21bd22
]
D0x4022e6|jmp qword ptr [rip
+
0x21bd24
]
J0x4022e6|
0x7f15489d0f10
/
/
hzytrace_linux.config未配置的函数默认打印四个参数
~~
16451
~~ libc.so.
6
!__libc_start_main N:
0x1
arg
0
:
0x402a00
arg
1
:
0x2
arg
2
:
0x7ffda586d668
arg
3
:
0x413bb0
/
/
ls的init
B0x413bb0|
0x413bdc
D0x413bb0|push r15
D0x413bb2|push r14
D0x413bb4|mov r15d, edi
D0x413bb7|push r13
D0x413bb9|push r12
D0x413bbb|lea r12, ptr [rip
+
0x20a23e
]
D0x413bc2|push rbp
D0x413bc3|lea rbp, ptr [rip
+
0x20a23e
]
D0x413bca|push rbx
D0x413bcb|mov r14, rsi
D0x413bce|mov r13, rdx
D0x413bd1|sub rbp, r12
D0x413bd4|sub rsp,
0x8
D0x413bd8|sar rbp,
0x3
D0x413bdc|call
0x4022b8
C0x413bdc|
0x4022b8
......
/
/
hzytrace_linux.config配置的函数根据设置的参数类型的打印参数信息
~~
16451
~~ libc.so.
6
!__lxstat N:
0x25b
arg
0
:
0x1
arg
1
:
0x7ffda586ce00
arg
2
:
0x246d3e0
arg
3
:
0x2
~~
16451
~~ libc.so.
6
!__lxstat64 N:
0x25c
arg
0
:
0x1
(
type
=
int
, size
=
0x4
)
arg
1
: pintool.log (
type
=
char
*
, size
=
0x0
)
arg
2
: (
type
=
char
*
, size
=
0x0
)
S|lstat:
6
executed libc.so.
6
!__lxstat returnIp:
0x4080c9
=
>
retval:
0x0
executed libc.so.
6
!__lxstat64 returnIp:
0x4080c9
=
>
retval:
0x0
(
type
=
int
, size
=
0x4
)
......
$ .
/
pin
-
t hzytrace.so
-
bbllog
0
-
-
ls
-
al
$ .
/
pin
-
t hzytrace.so
-
bbllog
0
-
-
ls
-
al
C0x4049c4|
0x402640
J0x4022e6|
0x7f93f9a77f10
~~
16821
~~ libc.so.
6
!__libc_start_main N:
0x1
arg
0
:
0x402a00
arg
1
:
0x2
arg
2
:
0x7ffda07a5b88
arg
3
:
0x413bb0
C0x413bdc|
0x4022b8
R0x4022d1|
0x413be1
C0x413bf9|
0x404a70
R0x404a49|
0x413bfd
R0x413c14|
0x7f93e5d6e7cf
C0x4049c4|
0x402640
J0x4022e6|
0x7f93f9a77f10
~~
16821
~~ libc.so.
6
!__libc_start_main N:
0x1
arg
0
:
0x402a00
arg
1
:
0x2
arg
2
:
0x7ffda07a5b88
arg
3
:
0x413bb0
C0x413bdc|
0x4022b8
R0x4022d1|
0x413be1
C0x413bf9|
0x404a70
R0x404a49|
0x413bfd
R0x413c14|
0x7f93e5d6e7cf
int
|syscall_read|
LONG
|__out
hex
^ARG2|
int
int
|syscall_write|
LONG
|char
*
int
|syscall_open|char
*
|
LONG
int
|syscall_read|
LONG
|__out
hex
^ARG2|
int
int
|syscall_write|
LONG
|char
*
int
|syscall_open|char
*
|
LONG
$ .
/
pin
-
t hzytrace.so
-
syscall
-
-
ls
-
al
$ .
/
pin
-
t hzytrace.so
-
syscall
-
-
ls
-
al
S|brk:
12
S|access:
21
S|access:
21
S|
open
:
2
SysEnter|syscall_open|
0x7f5ec45d41d1
|
0x80000
|
arg
0
:
/
etc
/
ld.so.cache (
type
=
char
*
, size
=
0x0
)
arg
1
:
0x80000
(
type
=
long
, size
=
0x8
)
SysExit|
open
S|fstat:
5
S|mmap:
9
S|close:
3
S|access:
21
S|
open
:
2
SysEnter|syscall_open|
0x7f5ec47dbd60
|
0x80000
|
arg
0
:
/
lib
/
x86_64
-
linux
-
gnu
/
libselinux.so.
1
(
type
=
char
*
, size
=
0x0
)
arg
1
:
0x80000
(
type
=
long
, size
=
0x8
)
SysExit|
open
S|read:
0
SysEnter|syscall_read|
0x3
|
0x7ffda586ce38
|
0x340
|
arg
0
:
0x3
(
type
=
long
, size
=
0x8
)
arg
2
:
0x340
(
type
=
int
, size
=
0x4
)
SysExit|read
arg
1
:
0x7ffda586ce38
000000
:
7f
45
4c
46
02
01
01
00
00
00
00
00
00
00
00
00
.ELF............
000010
:
03
00
3e
00
01
00
00
00
b0
5a
00
00
00
00
00
00
..>......Z......
000020
:
40
00
00
00
00
00
00
00
30
f5
01
00
00
00
00
00
@.......
0.
......
000030
:
00
00
00
00
40
00
38
00
08
00
40
00
1e
00
1d
00
....@.
8.
..@.....
000040
:
01
00
00
00
05
00
00
00
00
00
00
00
00
00
00
00
................
......
S|brk:
12
S|access:
21
S|access:
21
S|
open
:
2
SysEnter|syscall_open|
0x7f5ec45d41d1
|
0x80000
|
arg
0
:
/
etc
/
ld.so.cache (
type
=
char
*
, size
=
0x0
)
arg
1
:
0x80000
(
type
=
long
, size
=
0x8
)
SysExit|
open
S|fstat:
5
S|mmap:
9
S|close:
3
S|access:
21
S|
open
:
2
SysEnter|syscall_open|
0x7f5ec47dbd60
|
0x80000
|
arg
0
:
/
lib
/
x86_64
-
linux
-
gnu
/
libselinux.so.
1
(
type
=
char
*
, size
=
0x0
)
arg
1
:
0x80000
(
type
=
long
, size
=
0x8
)
SysExit|
open
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课