Tracer is suddenly acting so strange
Why not working tracer
Introduction
I recently use tools from linux to windows.
sometimes it has been and show me the very strange workflow.
like it.
1
2
3
4
5
6
7
8
9
10
180 ms fopen()
180 ms fopen()
181 ms fopen()
181 ms fopen()
181 ms fopen()
181 ms fopen()
182 ms fopen()
182 ms fopen()
183 ms fopen()
184 ms fopen()
I expect like..
1
2
3
4
5
6
7
8
9
10
180 ms fopen(path="path/to/file", mode="rb")
180 ms fopen(path="path/to/file", mode="rb")
181 ms fopen(path="path/to/file", mode="rb")
181 ms fopen(path="path/to/file", mode="rb")
181 ms fopen(path="path/to/file", mode="rb")
181 ms fopen(path="path/to/file", mode="rb")
182 ms fopen(path="path/to/file", mode="rb")
182 ms fopen(path="path/to/file", mode="rb")
183 ms fopen(path="path/to/file", mode="rb")
184 ms fopen(path="path/to/file", mode="rb")
So I check repository commit of tool and binary diff and check a update option list.. but i have no idea..
so I just reverse it for issue tracking :) I do not explain this feature archtecture, I just say code flow of tool.
What is that
it is very strong dynamic tracer for reverse.
sometime I use it. for develop and research.
Exploring Different Perspectives
Here we go.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def _create_stub_native_handler(self, target: TraceTarget, decorate: bool) -> str:
if target.flavor == "objc":
...
elif target.flavor == "swift":
...
else:
log_str = self._create_cstyle_logging_code(target, decorate)
return """\
defineHandler({
onEnter(log, args, state) {
log(%(log_str)s);
},
onLeave(log, retval, state) {
}
});
""" % {
"display_name": target.display_name,
"log_str": log_str,
}
here is generate code snippet.
Check a language from if condition.
so check a function of _create_cstyle_logging_code()
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def _create_cstyle_logging_code(self, target: TraceTarget, decorate: bool) -> str:
if decorate:
module_string = f" [{Path(target.scope).name}]"
else:
module_string = ""
args = self._generate_cstyle_argument_logging_code(target)
if len(args) == 0:
code = "'%(name)s()%(module_string)s'" % {"name": target.name, "module_string": module_string}
else:
code = "`%(name)s(%(args)s)%(module_string)s`" % {
"name": target.name,
"args": ", ".join(args),
"module_string": module_string,
}
return code
I think it is check a decorate option and check a number of args.
And go to function of _generate_cstyle_argument_logging_code()
.
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
def _generate_cstyle_argument_logging_code(self, target: TraceTarget) -> List[str]:
if self._manpages is None:
self._manpages = {}
try:
manroots = [
Path(d)
for d in subprocess.run(["manpath"], stdout=subprocess.PIPE, encoding="utf-8", check=True)
.stdout.strip()
.split(":")
]
for section in (2, 3):
for manroot in manroots:
mandir = manroot / f"man{section}"
if not mandir.exists():
continue
raw_section = str(section)
for entry in mandir.iterdir():
tokens = entry.name.split(".")
if len(tokens) < 2:
continue
if not tokens[1].startswith(raw_section):
continue
name = tokens[0]
if name in self._manpages:
continue
self._manpages[name] = (entry, section)
except:
return []
man_entry = self._manpages.get(target.name)
if man_entry is None:
return []
man_location, man_section = man_entry
try:
args = []
cfunc = next(f for f in self._read_manpage(man_location) if f.name == target.name)
for arg in cfunc.arguments:
if arg == "void":
continue
if arg.startswith("..."):
args.append("...")
continue
tokens = arg.split(" ")
arg_type = "".join(tokens[:-1])
arg_name = tokens[-1]
if arg_name.startswith("*"):
arg_type += "*"
arg_name = arg_name[1:]
elif arg_name.endswith("]"):
arg_type += "*"
arg_name = arg_name[: arg_name.index("[")]
read_ops = ""
annotate_pre = ""
annotate_post = ""
if arg_type.endswith("*restrict"):
arg_type = arg_type[:-8]
if arg_type in ("char*", "constchar*"):
read_ops = ".readUtf8String()"
annotate_pre = '"'
annotate_post = '"'
arg_index = len(args)
args.append(
"%(arg_name)s=%(annotate_pre)s${args[%(arg_index)s]%(read_ops)s}%(annotate_post)s"
% {
"arg_name": arg_name,
"arg_index": arg_index,
"read_ops": read_ops,
"annotate_pre": annotate_pre,
"annotate_post": annotate_post,
}
)
return args
except Exception:
return []
Yeah, it is parse API and generate args string like:
1
fopen(const char* file, int mode)
to
1
fopen(path="path/to/file", mode="rb")
We need check a this line.
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
try:
manroots = [
Path(d)
for d in subprocess.run(["manpath"], stdout=subprocess.PIPE, encoding="utf-8", check=True) # <=== Yeah, this is our troubleshooting point.
.stdout.strip()
.split(":")
]
for section in (2, 3):
for manroot in manroots:
mandir = manroot / f"man{section}"
if not mandir.exists():
continue
raw_section = str(section)
for entry in mandir.iterdir():
tokens = entry.name.split(".")
if len(tokens) < 2:
continue
if not tokens[1].startswith(raw_section):
continue
name = tokens[0]
if name in self._manpages:
continue
self._manpages[name] = (entry, section)
except:
return []
what is that?
First it is use ‘manpath’ from subprocess.
it is only use unix style.
and if it is appear exception go to except point from arch of try-catch.
so how to fix it? hahahaha
windows is just show me blank API
1
2
3
4
5
6
7
8
9
10
180 ms fopen()
180 ms fopen()
181 ms fopen()
181 ms fopen()
181 ms fopen()
181 ms fopen()
182 ms fopen()
182 ms fopen()
183 ms fopen()
184 ms fopen()
May be I think, we have a 2 way solution.
1.Use a declared API list.
like it.
1
2
3
4
5
6
FUNC_SIGNATURES = {
"write": ["int fd", "const void *buf", "size_t count"],
"open": ["const char *pathname", "int flags", "mode_t mode"],
"read": ["int fd", "void *buf", "size_t count"],
...
}
It is not good..
2.Parse Header libraries.
like it.
1
2
3
from pycparser import parse_file
ast = parse_file("/path/to/unistd.h", use_cpp=True)
it is not bad..but I can’t it. anyway it used other file and not automation script.
So.. how to contribute?
If you find any errors, please let me know by comment or email. Thank you.