When type_to_format / type_to_format_pair encounter a pointer field whose
pointee is reachable only through a typedef chain that ends at the
atomic 'void' or 'char' (e.g. PVOID -> VOID -> void, LPSTR -> CHAR ->
char, HANDLE -> ... -> void in some platform headers), they emit a bare
'*' and recurse into the pointee. The recursion produces nothing for
'void' (no format) and emits the legacy 'c' for 'char', so the
generated pf string ends up with either an orphan trailing/internal '*'
or the sequence '*c', which the new pf parser introduced in the
recent rewrite rejects: it requires '*' to be followed by a complete
dereferenceable spec ('z', a sized integer like 'd4'/'x2'/'u8', or
'?'). The result is parser warnings and dropped fields during 'tp':
rizin -k windows -c 'tp _OBJECT_ATTRIBUTES'
WARNING: pf: unknown specifier '*' at position 4, skipping
WARNING: pf: unknown specifier '*' at position 4, skipping
[only 4 of 6 fields rendered]
rizin -k windows -c 'tp _SYSTEM_INFO'
[11 fields collapse to 4]
rizin -k windows -c 'tp _STARTUPINFOA'
[three LPSTR fields render as '*c' which the parser cannot
usefully follow]
The top-level rz_type_as_format() already special-cases 'void *',
'char *', and callable pointers, mapping them to 'p' and 'z'. But the
inner walkers do not, because rz_type_is_void_ptr / rz_type_is_char_ptr
compare the literal identifier name and so do not see through typedefs
like VOID->void or CHAR->char.
Fix it by adding ptr_pointee_resolves_to(), a small static helper in
format.c that walks the typedb to find the canonical atomic name for
the pointee (bounded depth so a circular typedef cannot send the
resolver into an infinite loop), and using it in both POINTER branches
before the '*'+recurse fallback. Pointers whose pointee resolves to
'void' (or a void-aliased typedef) now emit 'p'; pointers whose pointee
resolves to 'char' (or a char-aliased typedef) emit 'z'. Everything
else continues to emit '*<inner>' unchanged, so single-level
LPBYTE -> BYTE -> unsigned char still renders as the perfectly valid
'*x1', and pointer-to-struct '*?' chains are untouched.
After the fix, the same upstream structs produce well-formed pf
strings:
ts _OBJECT_ATTRIBUTES -> 'x8p**x1x8pp ...' (two PVOID -> pp)
ts _SYSTEM_INFO -> 'x2x2d4ppx8d4d4d4x2x2 ...' (two LPVOID -> pp)
ts _STARTUPINFOA -> 'd4zzzd4...*x1ppp ...' (three LPSTR -> zzz;
LPBYTE still '*x1')
Add a regression test in test/db/cmd/cmd_pf that exercises both shapes
via 'ts _SECURITY_ATTRIBUTES' (single LPVOID) and 'ts _STARTUPINFOA'
(three LPSTR + one LPBYTE). Without this commit the test catches the
bug -- the LPVOID field becomes orphan '*' inside the format and the
LPSTR fields render as '*c'; with the commit both render cleanly as
documented above.
Also update one existing EXPECT in test/db/cmd/types: the 'td with
comments' test had encoded the legacy 'pf "d4[5]*c b foo"' shape for
'char *foo[5]'. With the fix this becomes 'pf "d4[5]z b foo"', which
is both well-formed under the new DSL and a more accurate description
(an array of zstrings rather than an array of pointers to a single
char).
Co-authored-by: Anton Kochkov <anton.kockov@gmail.com>
1081 lines
23 KiB
Text
1081 lines
23 KiB
Text
NAME=pf QQ
|
|
FILE==
|
|
CMDS=<<EOF
|
|
e asm.arch=arm
|
|
e cfg.bigendian=false
|
|
b 256
|
|
woe 0 255 0x11
|
|
pf Q
|
|
pf QQ
|
|
pfq QQ
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 = 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff
|
|
0x00000000 = 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff
|
|
0x00000010 = 10 21 32 43 54 65 76 87 98 a9 ba cb dc ed fe 0f
|
|
00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff
|
|
10 21 32 43 54 65 76 87 98 a9 ba cb dc ed fe 0f
|
|
EOF
|
|
RUN
|
|
|
|
NAME=pf.-x
|
|
FILE==
|
|
CMDS=<<EOF
|
|
pfn foo xxd
|
|
pfn~foo
|
|
pf- foo
|
|
pfn~foo
|
|
EOF
|
|
EXPECT=<<EOF
|
|
foo "xxd"
|
|
EOF
|
|
RUN
|
|
|
|
NAME=pf-*
|
|
FILE==
|
|
CMDS=<<EOF
|
|
pfn foo xxd
|
|
pfn~foo
|
|
pf-*
|
|
pfn~foo
|
|
EOF
|
|
EXPECT=<<EOF
|
|
foo "xxd"
|
|
EOF
|
|
RUN
|
|
|
|
NAME=pf i foo @x:0x01
|
|
FILE==
|
|
ARGS=-a x86 -b 32
|
|
CMDS=pf i foo @x:0x01
|
|
EXPECT=<<EOF
|
|
0x00000000 : foo = 1 [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=pf [3]ub
|
|
FILE==
|
|
CMDS=pf [3]ub
|
|
EXPECT=<<EOF
|
|
0x00000000 = [ 0, 0, 0 ] [LE]
|
|
0x0000000c = 0b0000_0000 [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=Cf main
|
|
FILE==
|
|
CMDS=Cf main;C*
|
|
EXPECT=
|
|
RUN
|
|
|
|
NAME=Cf 1 n2
|
|
FILE==
|
|
CMDS=Cf 1 n2;C
|
|
EXPECT=<<EOF
|
|
0x00000000 format 1 n2
|
|
EOF
|
|
RUN
|
|
|
|
NAME=seteq
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
pfn foo "x4x4d4 foo bar cow"
|
|
w hello happy world
|
|
w goodbye cruel world @ 0x20
|
|
s 0x20
|
|
pf. foo @ 0x00
|
|
pfa foo
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : foo = 0x6c6c6568 [LE]
|
|
0x00000004 : bar = 0x6168206f [LE]
|
|
0x00000008 : cow = 544829552 [LE]
|
|
0x00000020 : foo = 0x646f6f67 [LE]
|
|
0x00000024 : bar = 0x20657962 [LE]
|
|
0x00000028 : cow = 1702195811 [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=float
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=arm
|
|
e cfg.bigendian=false
|
|
wx 00007a45457a0000
|
|
e cfg.bigendian=false
|
|
pf ff
|
|
wx 00007a45457a0000
|
|
e cfg.bigendian=true
|
|
pf ff
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 = 4000 [LE]
|
|
0x00000004 = 4.38620432e-41 [LE]
|
|
0x00000000 = 4000 [LE]
|
|
0x00000004 = 4.38620432e-41 [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=seteq2
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
pfn foo "x4d4 foo bar"
|
|
pf. foo
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : foo = 0x00000000 [LE]
|
|
0x00000004 : bar = 0 [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=types
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
wx 00007a452a4b9a0200002a
|
|
pf fcb1d4C foo bar fool beer plop
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : foo = 4000 [LE]
|
|
0x00000004 : bar = '*'
|
|
0x00000005 : fool = 0b0100_1011 [LE]
|
|
0x00000006 : beer = 666 [LE]
|
|
0x0000000a : plop = 42 [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=word types
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
wx efbeadde002a0000adde
|
|
pf x8x2 bigWord beef
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : bigWord = 0x00002a00deadbeef [LE]
|
|
0x00000008 : beef = 0xdead [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=Register
|
|
# The legacy 'r (regname)' form looked up a CPU register by name and
|
|
# printed its value (via RzPrint::get_register). The new parser
|
|
# repurposes 'r' as "raw hex byte dump", so the register-fetch path
|
|
# is gone -- the test is kept as BROKEN with this comment so the
|
|
# regression is tracked. Restoring would mean wiring a new
|
|
# register-lookup hook through RzPfCtx, which is outside the scope of
|
|
# the parser rewrite.
|
|
BROKEN=1
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
e asm.bits=32
|
|
e asm.arch=x86
|
|
e analysis.arch=x86
|
|
ar eax=4000
|
|
ar eip=42
|
|
pfn plop "rr (eax)reg1 (eip)reg2"
|
|
pf. plop
|
|
pf.j plop
|
|
EOF
|
|
EXPECT=<<EOF
|
|
reg1 : eax : 0x00000fa0
|
|
reg2 : eip : 0x0000002a
|
|
[{"name":"reg1","type":"r","offset":0,"value":4000},{"name":"reg2","type":"r","offset":0,"value":42}]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=Pointers
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
wx 30
|
|
wx 20 @ 0x04
|
|
wx 40 @ 0x08
|
|
wx 2a @ 0x20
|
|
w TROLL @ 0x30
|
|
wx a00f @ 0x40
|
|
e asm.bits=32 # pointer size
|
|
pfn plop *z*d4*x2 nb name blob
|
|
pf. plop
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : nb = (*0x30) "TROLL"
|
|
0x00000004 : name = (*0x20) 42
|
|
0x00000008 : blob = (*0x40) 0x0fa0
|
|
EOF
|
|
RUN
|
|
|
|
NAME=Pointer sizes
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
e asm.bits=32
|
|
wx added0dec0de5eba7ada1eab11caefbeadde0bb0
|
|
pf p2p4p8pp2
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 = 0xdead
|
|
0x00000002 = 0xdec0ded0
|
|
0x00000006 = 0xca11ab1eda7aba5e
|
|
0x0000000e = 0xdeadbeef
|
|
0x00000012 = 0xb00b
|
|
EOF
|
|
RUN
|
|
|
|
NAME=swap endianess
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
wx deadbeef00000000adde
|
|
pf X8X2 bigWord beef
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : bigWord = 0xdeadbeef00000000 [BE]
|
|
0x00000008 : beef = 0xadde [BE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=String pointer
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
w TROLL @ 0x30
|
|
wx 30
|
|
wx a00f @ 0x04
|
|
e asm.bits=32
|
|
pf *zd4 Pouet Plop
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : Pouet = (*0x30) "TROLL"
|
|
0x00000004 : Plop = 4000 [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=pf format from typedef'd void* / char* (orphan-* regression)
|
|
FILE==
|
|
ARGS=-a x86 -b 64 -k windows
|
|
CMDS=<<EOF
|
|
ts _SECURITY_ATTRIBUTES
|
|
ts _STARTUPINFOA
|
|
EOF
|
|
EXPECT=<<EOF
|
|
pf "d4pd4 nLength (LPVOID)lpSecurityDescriptor bInheritHandle"
|
|
pf "d4*c*c*cd4d4d4d4d4d4d4d4x2x2*x1ppp cb (LPSTR)lpReserved (LPSTR)lpDesktop (LPSTR)lpTitle dwX dwY dwXSize dwYSize dwXCountChars dwYCountChars dwFillAttribute dwFlags wShowWindow cbReserved2 (LPBYTE)lpReserved2 hStdInput hStdOutput hStdError"
|
|
EOF
|
|
RUN
|
|
|
|
NAME=timestamp
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
wx 321ED92D90DF5254
|
|
pf tt troll plop
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : troll = [unix32] [LE] 1994-05-17 19:42:42 UTC
|
|
0x00000004 : plop = [unix32] [LE] 2014-10-31 01:02:08 UTC
|
|
EOF
|
|
RUN
|
|
|
|
NAME=named obj
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
wx a00f00004b
|
|
pfn troll "d4c lol cat"
|
|
pf. troll
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : lol = 4000 [LE]
|
|
0x00000004 : cat = 'K'
|
|
EOF
|
|
RUN
|
|
|
|
NAME=array obj
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
wx a00f00004b2a0000004c
|
|
pfn troll "2d4c nb plop"
|
|
pf. troll
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : nb = 4000 [LE]
|
|
0x00000004 : plop = 'K'
|
|
0x00000005 : nb = 42 [LE]
|
|
0x00000009 : plop = 'L'
|
|
EOF
|
|
RUN
|
|
|
|
NAME=write test
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
wx 32000000424c41424c41424c41424c41
|
|
pfn troll "d4zd4 hu swagg plop"
|
|
pfw troll.hu 42
|
|
pfw troll.swagg "B*A AA"
|
|
pfw troll.plop 4000
|
|
pf. troll
|
|
EOF
|
|
EXPECT=<<EOF
|
|
hu : 0x00000000 = 42
|
|
swagg : 0x00000004 = "B*A AABLABLA"
|
|
plop : 0x00000011 = 4000
|
|
0x00000000 : hu = 42 [LE]
|
|
0x00000004 : swagg = "B*A AABLABLA"
|
|
0x00000011 : plop = 4000 [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=write wide string
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
wx 42004c00410042004c00410042004c00410042004c0041000000a00f0000
|
|
pfn troll "Zd4 swagg plop"
|
|
pf. troll
|
|
pfw troll.swagg "BWA AA"
|
|
pfw troll.plop "42"
|
|
pf. troll
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : swagg = "BLABLABLABLA"
|
|
0x0000001a : plop = 4000 [LE]
|
|
swagg : 0x00000000 = "BWA AABLABLA"
|
|
plop : 0x0000001a = 42
|
|
0x00000000 : swagg = "BWA AABLABLA"
|
|
0x0000001a : plop = 42 [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=fixed size variable
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
wx a00f0000000000002a412f00007a4500000000402a44adde00000000efbeadde00000000000000000000000040
|
|
pf [2]d4[3]b1[2]f4[3]c[3]x2[2]x8[6]x4
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 = [ 4000, 0 ] [LE]
|
|
0x00000008 = [ 0b0010_1010, 0b0100_0001, 0b0010_1111 ] [LE]
|
|
0x0000000b = [ 4000, 0 ] [LE]
|
|
0x00000013 = [ '@', '*', 'D' ]
|
|
0x00000016 = [ 0xdead, 0x0000, 0x0000 ] [LE]
|
|
0x0000001c = [ 0x00000000deadbeef, 0x0000000000000000 ] [LE]
|
|
0x0000002c = [ 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 ] [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=fixed size str, widechar, and var
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
w TROLL
|
|
wx 12 @ 0x02
|
|
wx a00f @ 0x0a
|
|
ww PLOP @ 0x16
|
|
wx 2a @ 0x2a
|
|
pf [10]z[3]d4[10]Zb1
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 = "TR\x12LL"
|
|
0x0000000a = [ 4000, 0, 0 ] [LE]
|
|
0x00000016 = "PLOP"
|
|
0x00000020 = 0b0000_0000 [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=Enum test
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
e asm.bits=32
|
|
td enum troll { BITE=42, PATE=4000};
|
|
wx a00f
|
|
pf E (troll)plop
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : plop = 0x00000fa0 ; PATE
|
|
EOF
|
|
RUN
|
|
|
|
NAME=32 bit twice then string
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
e asm.bits=32
|
|
wv 0x10
|
|
wv 0x10 @ 4
|
|
w hello @ 0x10
|
|
pf ss
|
|
pf *x4*x4
|
|
pf *z*z
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 = (*0x10) "hello"
|
|
0x00000004 = (*0x10) "hello"
|
|
0x00000000 = (*0x10) 0x6c6c6568
|
|
0x00000004 = (*0x10) 0x6c6c6568
|
|
0x00000000 = (*0x10) "hello"
|
|
0x00000004 = (*0x10) "hello"
|
|
EOF
|
|
RUN
|
|
|
|
NAME=simple union test
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
e asm.bits=32
|
|
wv 0x2a
|
|
pf 0iw integer word
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : integer = 42 [LE]
|
|
0x00000000 : word = 0x002a [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=simple nested struct
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
e asm.bits=32
|
|
wx 2a
|
|
wx a00f @ 0x04
|
|
wx 2a @ 0x08
|
|
wx 10 @ 0x0a
|
|
wx efbe @ 0x0e
|
|
wx 20 @ 0x10
|
|
pfn troll "d4x2 integer word"
|
|
pfn plop "d4??d4 firstInt (troll)One (troll)Two secondInt"
|
|
pf. plop
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : firstInt = 42 [LE]
|
|
0x00000004 : One = struct<troll> {
|
|
0x00000004 : integer = 4000 [LE]
|
|
0x00000008 : word = 0x002a [LE]
|
|
}
|
|
0x0000000a : Two = struct<troll> {
|
|
0x0000000a : integer = 16 [LE]
|
|
0x0000000e : word = 0xbeef [LE]
|
|
}
|
|
0x00000010 : secondInt = 32 [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=nested struct
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
e asm.bits=32
|
|
wx 2a000000a00f00001234100000006416
|
|
wx 2a0000002a @ 0x10
|
|
pfn troll "d4x2*? integer word (troll)Bah"
|
|
pfn plop "d4?x2 firstInt (troll)Boh plop"
|
|
pf. plop
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : firstInt = 42 [LE]
|
|
0x00000004 : Boh = struct<troll> {
|
|
0x00000004 : integer = 4000 [LE]
|
|
0x00000008 : word = 0x3412 [LE]
|
|
0x0000000a : Bah = (*0x10) struct<troll> {
|
|
0x00000010 : integer = 42 [LE]
|
|
0x00000014 : word = 0x002a [LE]
|
|
0x00000016 : Bah = (*0x0)
|
|
}
|
|
}
|
|
0x0000000e : plop = 0x1664 [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=nested unions
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
e asm.bits=32
|
|
wx 2a000000a00f0000a02000000172
|
|
pfn struct "x4x4 first second"
|
|
pfn union "0d4?x2 integer (struct)swagg word"
|
|
pfn plop "d4?x2 firstInt (union)Boh plop"
|
|
pf. plop
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : firstInt = 42 [LE]
|
|
0x00000004 : Boh = struct<union> {
|
|
0x00000004 : integer = 4000 [LE]
|
|
0x00000004 : swagg = struct<struct> {
|
|
0x00000004 : first = 0x00000fa0 [LE]
|
|
0x00000008 : second = 0x000020a0 [LE]
|
|
}
|
|
0x00000004 : word = 0x0fa0 [LE]
|
|
}
|
|
0x0000000c : plop = 0x7201 [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=complex nested struct
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
e asm.bits=32
|
|
wx 341289679a020000a00f00002a003000000014426416
|
|
wx 800600000040 @ 0x20
|
|
wx 14000000641620000000 @ 0x30
|
|
pfn troll "d4x2*? integer word (troll)Bah"
|
|
pfn plop "d4?x2 first (troll)Boh bwa"
|
|
pfn gobelin "x2x2?x4 blah meh (plop)Buh foo"
|
|
pf. gobelin
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : blah = 0x1234 [LE]
|
|
0x00000002 : meh = 0x6789 [LE]
|
|
0x00000004 : Buh = struct<plop> {
|
|
0x00000004 : first = 666 [LE]
|
|
0x00000008 : Boh = struct<troll> {
|
|
0x00000008 : integer = 4000 [LE]
|
|
0x0000000c : word = 0x002a [LE]
|
|
0x0000000e : Bah = (*0x30) struct<troll> {
|
|
0x00000030 : integer = 20 [LE]
|
|
0x00000034 : word = 0x1664 [LE]
|
|
0x00000036 : Bah = (*0x20) struct<troll> {
|
|
0x00000020 : integer = 1664 [LE]
|
|
0x00000024 : word = 0x4000 [LE]
|
|
0x00000026 : Bah = (*0x0)
|
|
}
|
|
}
|
|
}
|
|
0x00000012 : bwa = 0x4214 [LE]
|
|
}
|
|
0x00000014 : foo = 0x00001664 [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=flag for nested struct
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
e asm.bits=32
|
|
wx 341289679a020000a00f00002a00300000001442
|
|
wx 800600000040 @ 0x20
|
|
wx 14000000641620000000 @ 0x30
|
|
pfn troll "d4x2*? integer word (troll)Bah"
|
|
pfn plop "d4?x2 first (troll)Boh bwa"
|
|
pfn gobelin "x2x2? blah meh (plop)Buh"
|
|
pf. gobelin
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : blah = 0x1234 [LE]
|
|
0x00000002 : meh = 0x6789 [LE]
|
|
0x00000004 : Buh = struct<plop> {
|
|
0x00000004 : first = 666 [LE]
|
|
0x00000008 : Boh = struct<troll> {
|
|
0x00000008 : integer = 4000 [LE]
|
|
0x0000000c : word = 0x002a [LE]
|
|
0x0000000e : Bah = (*0x30) struct<troll> {
|
|
0x00000030 : integer = 20 [LE]
|
|
0x00000034 : word = 0x1664 [LE]
|
|
0x00000036 : Bah = (*0x20) struct<troll> {
|
|
0x00000020 : integer = 1664 [LE]
|
|
0x00000024 : word = 0x4000 [LE]
|
|
0x00000026 : Bah = (*0x0)
|
|
}
|
|
}
|
|
}
|
|
0x00000012 : bwa = 0x4214 [LE]
|
|
}
|
|
EOF
|
|
RUN
|
|
|
|
NAME=struct size
|
|
FILE=malloc://256
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
e asm.bits=32
|
|
pfn plop "x2d4 word int"
|
|
pfn troll "x1cd4x2x8fd4o4x4s:S.[4]z[2]B[4]E? byte char int word quad float hexa octal hex strp wstrp str bitfield enum (plop)struct"
|
|
pfs troll
|
|
EOF
|
|
EXPECT=<<EOF
|
|
50
|
|
EOF
|
|
RUN
|
|
|
|
NAME=Print value only
|
|
FILE=bins/pe/ch22.exe
|
|
ARGS=-nn
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
e asm.bits=32
|
|
s 0x80
|
|
pfv .pe_nt_image_headers32.optionalHeader.dataDirectory[5].virtualAddress
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x0000c000
|
|
EOF
|
|
RUN
|
|
|
|
NAME=print signed and unsigned values
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
wx 71776572747975696f706173646667686a6b6c7a786376626e6d71776572747975696f706173646667686a6b6c7a786376626e6d
|
|
pf U8..U4.U2:U1..u8..u4u2u1 a b c d e f
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : a = 8176115190769218921 [BE]
|
|
0x0000000a : b = 1634952294 [BE]
|
|
0x0000000f : c = 26730 [BE]
|
|
0x00000011 : d = 0x6b
|
|
0x00000012 : e = 108 [BE]
|
|
0x00000015 : f = 7311437234876610147 [LE]
|
|
0x0000001f = 1869182329 [LE]
|
|
0x00000023 = 24944 [LE]
|
|
0x00000025 = 115 [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=Combining flags, backtick, and var length array
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
e asm.bits=32
|
|
f test 4 @ 0x20
|
|
w SWAG
|
|
wx 04 @ test
|
|
wx 20 @ 0x4
|
|
pfn plop "d4p int ptr"
|
|
pf [`pfv p @ test`]c
|
|
pf [*`pfv .plop.ptr`]c
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 = 'S'
|
|
0x00000000 = 'S'
|
|
EOF
|
|
RUN
|
|
|
|
NAME=print n-times a format
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
e asm.bits=64
|
|
wx 71776572747975696f706173646667686a6b6c7a786376626e6d71776572747975696f706173646667686a6b6c7a786376626e6d
|
|
pfn plop "d4p int ptr"
|
|
pf {2}? (plop)structname @ 0
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : structname = struct<plop> {
|
|
0x00000000 : int = 1919252337 [LE]
|
|
0x00000004 : ptr = 0x7361706f69757974
|
|
}
|
|
0x0000000c : structname = struct<plop> {
|
|
0x0000000c : int = 1751606884 [LE]
|
|
0x00000010 : ptr = 0x627663787a6c6b6a
|
|
}
|
|
EOF
|
|
RUN
|
|
|
|
NAME=print with byte(s) skip
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
e asm.bits=64
|
|
wx 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
|
|
pfn abc "d4c...d4:pd4d4 a b c d e f"
|
|
pf. abc
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : a = 50462976 [LE]
|
|
0x00000004 : b = '.'
|
|
0x00000008 : c = 185207048 [LE]
|
|
0x0000000c : d = 0x0c
|
|
0x0000000d : e = 0x14131211100f0e0d
|
|
0x00000015 : f = 404166165 [LE]
|
|
0x00000019 = 471538201 [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=PE test
|
|
FILE=bins/pe/ch22.exe
|
|
ARGS=-nn
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
s 0x80
|
|
pf. pe_nt_image_headers32
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000080 : signature = "PE"
|
|
0x00000084 : fileHeader = struct<pe_image_file_header> {
|
|
0x00000084 : machine = 0x0000014c ; IMAGE_FILE_MACHINE_I386
|
|
0x00000086 : numberOfSections = 0x0004 [LE]
|
|
0x00000088 : timeDateStamp = [unix32] [LE] 2014-09-11 18:21:46 UTC
|
|
0x0000008c : pointerToSymbolTable = 0x00000000 [LE]
|
|
0x00000090 : numberOfSymbols = 0x00000000 [LE]
|
|
0x00000094 : sizeOfOptionalHeader = 0x00e0 [LE]
|
|
0x00000096 : characteristics = 0x00000102 : IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_32BIT_MACHINE
|
|
}
|
|
0x00000098 : optionalHeader = struct<pe_image_optional_header32> {
|
|
0x00000098 : magic = 0x0000010b ; IMAGE_NT_OPTIONAL_HDR32_MAGIC
|
|
0x0000009a : majorLinkerVersion = 0x0b [LE]
|
|
0x0000009b : minorLinkerVersion = 0x00 [LE]
|
|
0x0000009c : sizeOfCode = 0x00003000 [LE]
|
|
0x000000a0 : sizeOfInitializedData = 0x00003400 [LE]
|
|
0x000000a4 : sizeOfUninitializedData = 0x00000000 [LE]
|
|
0x000000a8 : addressOfEntryPoint = 0x00004f3e [LE]
|
|
0x000000ac : baseOfCode = 0x00002000 [LE]
|
|
0x000000b0 : baseOfData = 0x00006000 [LE]
|
|
0x000000b4 : imageBase = 0x00400000 [LE]
|
|
0x000000b8 : sectionAlignment = 0x00002000 [LE]
|
|
0x000000bc : fileAlignment = 0x00000200 [LE]
|
|
0x000000c0 : majorOperatingSystemVersion = 0x0004 [LE]
|
|
0x000000c2 : minorOperatingSystemVersion = 0x0000 [LE]
|
|
0x000000c4 : majorImageVersion = 0x0000 [LE]
|
|
0x000000c6 : minorImageVersion = 0x0000 [LE]
|
|
0x000000c8 : majorSubsystemVersion = 0x0006 [LE]
|
|
0x000000ca : minorSubsystemVersion = 0x0000 [LE]
|
|
0x000000cc : win32VersionValue = 0x00000000 [LE]
|
|
0x000000d0 : sizeOfImage = 0x0000e000 [LE]
|
|
0x000000d4 : sizeOfHeaders = 0x00000400 [LE]
|
|
0x000000d8 : checkSum = 0x00000000 [LE]
|
|
0x000000dc : subsystem = 0x00000002 ; IMAGE_SUBSYSTEM_WINDOWS_GUI
|
|
0x000000de : dllCharacteristics = 0x00008560 : IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE | IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_NO_SEH | IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
|
|
0x000000e0 : sizeOfStackReserve = 0x00100000 [LE]
|
|
0x000000e4 : sizeOfStackCommit = 0x00001000 [LE]
|
|
0x000000e8 : sizeOfHeapReserve = 0x00100000 [LE]
|
|
0x000000ec : sizeOfHeapCommit = 0x00001000 [LE]
|
|
0x000000f0 : loaderFlags = 0x00000000 [LE]
|
|
0x000000f4 : numberOfRvaAndSizes = 0x00000010 [LE]
|
|
0x000000f8 : dataDirectory = struct<pe_image_data_directory> {
|
|
0x000000f8 : virtualAddress = 0x00000000 [LE]
|
|
0x000000fc : size = 0x00000000 [LE]
|
|
0x00000100 : virtualAddress = 0x00004ef0 [LE]
|
|
0x00000104 : size = 0x0000004b [LE]
|
|
0x00000108 : virtualAddress = 0x00008000 [LE]
|
|
0x0000010c : size = 0x00002e40 [LE]
|
|
0x00000110 : virtualAddress = 0x00000000 [LE]
|
|
0x00000114 : size = 0x00000000 [LE]
|
|
0x00000118 : virtualAddress = 0x00000000 [LE]
|
|
0x0000011c : size = 0x00000000 [LE]
|
|
0x00000120 : virtualAddress = 0x0000c000 [LE]
|
|
0x00000124 : size = 0x0000000c [LE]
|
|
0x00000128 : virtualAddress = 0x00006000 [LE]
|
|
0x0000012c : size = 0x0000001c [LE]
|
|
0x00000130 : virtualAddress = 0x00000000 [LE]
|
|
0x00000134 : size = 0x00000000 [LE]
|
|
0x00000138 : virtualAddress = 0x00000000 [LE]
|
|
0x0000013c : size = 0x00000000 [LE]
|
|
0x00000140 : virtualAddress = 0x00000000 [LE]
|
|
0x00000144 : size = 0x00000000 [LE]
|
|
0x00000148 : virtualAddress = 0x00000000 [LE]
|
|
0x0000014c : size = 0x00000000 [LE]
|
|
0x00000150 : virtualAddress = 0x00000000 [LE]
|
|
0x00000154 : size = 0x00000000 [LE]
|
|
0x00000158 : virtualAddress = 0x00002000 [LE]
|
|
0x0000015c : size = 0x00000008 [LE]
|
|
0x00000160 : virtualAddress = 0x00000000 [LE]
|
|
0x00000164 : size = 0x00000000 [LE]
|
|
0x00000168 : virtualAddress = 0x00002008 [LE]
|
|
0x0000016c : size = 0x00000048 [LE]
|
|
0x00000170 : virtualAddress = 0x00000000 [LE]
|
|
0x00000174 : size = 0x00000000 [LE]
|
|
}
|
|
}
|
|
EOF
|
|
RUN
|
|
|
|
NAME=Variable length array
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
e asm.bits=32
|
|
wx 2a @ 0x20
|
|
pf [*0x20]c
|
|
pf [(42-21-11)/2]c
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 = '.'
|
|
0x00000000 = '.'
|
|
EOF
|
|
RUN
|
|
|
|
NAME=Infinite Recursion segfault 1
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
pfn _NT_TIB "? (_NT_TIB)Self"
|
|
pf. _NT_TIB > /dev/null
|
|
pfn~NT_TIB
|
|
EOF
|
|
EXPECT=<<EOF
|
|
_NT_TIB "? (_NT_TIB)Self"
|
|
EOF
|
|
RUN
|
|
|
|
NAME=Infinite Recursion segfault 2
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
pfn _NT_TIB "pppppd4p? ExceptionList StackBase StackLimit SubSystemTib FiberData Version ArbitraryUserPointer (_NT_TIB)Self"
|
|
pf. _NT_TIB > /dev/null
|
|
pfn~NT_TIB
|
|
EOF
|
|
EXPECT=<<EOF
|
|
_NT_TIB "pppppd4p? ExceptionList StackBase StackLimit SubSystemTib FiberData Version ArbitraryUserPointer (_NT_TIB)Self"
|
|
EOF
|
|
RUN
|
|
|
|
NAME=One byte enum endianness
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=arm
|
|
e cfg.bigendian=true
|
|
wb 4142434431323334
|
|
td "enum ascii{ LETTER_A=0x41, LETTER_D=0x44, DIGIT_1=0x31, DIGIT_4=0x34}"
|
|
pfn somestring "[1]E[1]E[1]E[1]E[1]E[1]E[1]E[1]E (ascii)B1 (ascii)B2 (ascii)B3 (ascii)B4 (ascii)B5 (ascii)B6 (ascii)B7 (ascii)B8"
|
|
pf. somestring
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : B1 = 0x00000041 ; LETTER_A
|
|
0x00000001 : B2 = 0x00000042
|
|
0x00000002 : B3 = 0x00000043
|
|
0x00000003 : B4 = 0x00000044 ; LETTER_D
|
|
0x00000004 : B5 = 0x00000031 ; DIGIT_1
|
|
0x00000005 : B6 = 0x00000032
|
|
0x00000006 : B7 = 0x00000033
|
|
0x00000007 : B8 = 0x00000034 ; DIGIT_4
|
|
EOF
|
|
RUN
|
|
|
|
NAME=union pf
|
|
FILE=malloc://1024
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
wv4 1234
|
|
pf "d4;d4"
|
|
pf "d4,,,,d4"
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 = 1234 [LE]
|
|
0x00000004 = 0 [LE]
|
|
0x00000000 = 1234 [LE]
|
|
0x00000004 = 0 [LE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=pf
|
|
FILE=bins/elf/crackme0x05
|
|
CMDS=pf 2F
|
|
EXPECT=<<EOF
|
|
0x080483d0 = 3.4042736339637191e-68 [BE]
|
|
0x080483d8 = 9.4124612178635506e+78 [BE]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=pf z, scr.strconv and str.escbslash
|
|
FILE==
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
wz \x7fabc\\123\n
|
|
(print strconv escbslash; e scr.strconv=${strconv}; e str.escbslash=${escbslash}; pf z)
|
|
.(print asciiesc false)
|
|
.(print asciiesc true)
|
|
.(print asciidot false)
|
|
.(print asciidot true)
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 = "\x7fabc\\123\n"
|
|
0x00000000 = "\x7fabc\\123\n"
|
|
0x00000000 = "\x7fabc\\123\n"
|
|
0x00000000 = "\x7fabc\\123\n"
|
|
EOF
|
|
RUN
|
|
|
|
NAME=pfj and triply-nested struct
|
|
FILE==
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
wv2 0x1234
|
|
wv4 0x56789abc @ 0x2
|
|
wv8 0xdef0123456789abc @ 0x6
|
|
pfn third "x2 t1"
|
|
pfn second "?x4 (third)t s1"
|
|
pfn first "?x8 (second)s f1"
|
|
pf. first
|
|
echo
|
|
pf.j first~{}
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : s = struct<second> {
|
|
0x00000000 : t = struct<third> {
|
|
0x00000000 : t1 = 0x1234 [LE]
|
|
}
|
|
0x00000002 : s1 = 0x56789abc [LE]
|
|
}
|
|
0x00000006 : f1 = 0xdef0123456789abc [LE]
|
|
|
|
[
|
|
{
|
|
"name": "s",
|
|
"type": "unknown",
|
|
"offset": 0,
|
|
"struct_type": "second",
|
|
"fields": [
|
|
{
|
|
"name": "t",
|
|
"type": "unknown",
|
|
"offset": 0,
|
|
"struct_type": "third",
|
|
"fields": [
|
|
{
|
|
"name": "t1",
|
|
"type": "hex",
|
|
"size": 2,
|
|
"offset": 0,
|
|
"endian": "little",
|
|
"value": 4660
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "s1",
|
|
"type": "hex",
|
|
"size": 4,
|
|
"offset": 2,
|
|
"endian": "little",
|
|
"value": 1450744508
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "f1",
|
|
"type": "hex",
|
|
"size": 8,
|
|
"offset": 6,
|
|
"endian": "little",
|
|
"value": 16064359886828903100
|
|
}
|
|
]
|
|
EOF
|
|
RUN
|
|
|
|
NAME=pfj and Matryoshka dolls
|
|
FILE==
|
|
CMDS=<<EOF
|
|
e asm.arch=x86
|
|
wx 7f
|
|
wv8 0xdef0123456789abc @ 0x1
|
|
pfn fourth "x1 fo1"
|
|
pfn third "? (fourth)fo"
|
|
pfn second "? (third)t"
|
|
pfn start "?x8 (second)s f1"
|
|
pf. start
|
|
echo
|
|
pf.j start~{}
|
|
echo
|
|
pfn full "? (second)s"
|
|
pf. full
|
|
echo
|
|
pf.j full~{}
|
|
EOF
|
|
EXPECT=<<EOF
|
|
0x00000000 : s = struct<second> {
|
|
0x00000000 : t = struct<third> {
|
|
0x00000000 : fo = struct<fourth> {
|
|
0x00000000 : fo1 = 0x7f [LE]
|
|
}
|
|
}
|
|
}
|
|
0x00000001 : f1 = 0xdef0123456789abc [LE]
|
|
|
|
[
|
|
{
|
|
"name": "s",
|
|
"type": "unknown",
|
|
"offset": 0,
|
|
"struct_type": "second",
|
|
"fields": [
|
|
{
|
|
"name": "t",
|
|
"type": "unknown",
|
|
"offset": 0,
|
|
"struct_type": "third",
|
|
"fields": [
|
|
{
|
|
"name": "fo",
|
|
"type": "unknown",
|
|
"offset": 0,
|
|
"struct_type": "fourth",
|
|
"fields": [
|
|
{
|
|
"name": "fo1",
|
|
"type": "hex",
|
|
"size": 1,
|
|
"offset": 0,
|
|
"endian": "little",
|
|
"value": 127
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "f1",
|
|
"type": "hex",
|
|
"size": 8,
|
|
"offset": 1,
|
|
"endian": "little",
|
|
"value": 16064359886828903100
|
|
}
|
|
]
|
|
|
|
0x00000000 : s = struct<second> {
|
|
0x00000000 : t = struct<third> {
|
|
0x00000000 : fo = struct<fourth> {
|
|
0x00000000 : fo1 = 0x7f [LE]
|
|
}
|
|
}
|
|
}
|
|
|
|
[
|
|
{
|
|
"name": "s",
|
|
"type": "unknown",
|
|
"offset": 0,
|
|
"struct_type": "second",
|
|
"fields": [
|
|
{
|
|
"name": "t",
|
|
"type": "unknown",
|
|
"offset": 0,
|
|
"struct_type": "third",
|
|
"fields": [
|
|
{
|
|
"name": "fo",
|
|
"type": "unknown",
|
|
"offset": 0,
|
|
"struct_type": "fourth",
|
|
"fields": [
|
|
{
|
|
"name": "fo1",
|
|
"type": "hex",
|
|
"size": 1,
|
|
"offset": 0,
|
|
"endian": "little",
|
|
"value": 127
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
EOF
|
|
RUN
|