There is yet another ARM/THUMB pattern finder.
Main features:
- Compatible with Smelter patterns syntax.
- Compatible with Ghidra SRE patterns syntax.
- Enhanced patterns syntax:
- Nested patterns for LDR.
- Half-byte patterns.
- Bitmask patterns.
- JSON output.
The name was chosen in respect to Viktor89, who is greatest patch porter in the Siemens Mobile modding scene.
- Windows: download .exe in Releases.
- ArchLinux:
yay -S ptr89-git
- Ubuntu/Debian/Fedora/OpenSUSE repository
- Old Ubuntu/Debian: download .deb in Releases.
- Build from sources:
# Ubuntu/Debian fakeroot debian/rules binary # OSX/Linux/Unix mkdir build cd build cmake .. make -j$(nproc)
Usage: ptr89 [arguments]
Global options:
-h, --help show this help
-f, --file FILE fullflash file [required]
-b, --base HEX fullflash base address [default: A0000000]
-a, --align N search align [default: 1]
-V, --verbose enable debug
-J, --json output as JSON
Find patterns:
-p, --pattern STRING pattern to search
-n, --limit NUMBER limit results count [default 100]
Find xrefs:
-x, --xref HEX address to search
-n, --limit NUMBER limit results count [default 100]
Find patterns from functions.ini:
--from-ini FILE path to functions.ini
Prettify pattern:
--prettify STRING pattern
$ ptr89 -f EL71sw45.bin -x A04CA048
Searching x-refs for A04CA048
Found 3 matches:
A0CF63A4 (branch call)
A0FC25DC (branch call)
A0FC25E0 (pointer)
Search done in 1612 ms
$ ptr89 -f EL71v45.bin -p "F0B5061C0C1C151C85B068461122??49??????????E0207869466A460009085C307021780134"
Pattern: 'F0B5061C0C1C151C85B068461122??49??????????E0207869466A460009085C307021780134'
Found 1 matches:
A058BB98: A058BB99 (offset)
Search done in 72 ms
$ ptr89 -f EL71v45.bin -p "??2800D0F5E6704780B508F0??E980BD80B5+1" -p "??B589B006A901A80522??????????49051C"
Pattern: '??2800D0F5E6704780B508F0??E980BD80B5+1'
Found 1 matches:
A0092F93: A0092F93 (offset)
Pattern: '??B589B006A901A80522??????????49051C'
Found 1 matches:
A05C4B38: A05C4B39 (offset)
Search done in 143 ms
ptr89 -f EL71v45.bin --from-ini ELKA.ini > swilib.vkp
Syntax is fully compatible with WinHex, Smelter and Ghidra SRE patterns.
# Exact match one byte
B5
# Match ANY one byte
??
# Match one byte by half-byte mask
# ? is wildcard for any 4bit part of byte
2?
?2
# Match one byte by bit mask
# . is wildcard for bit
[1111....]
You can use spaces or commas to separate different bytes or groups.
All these patterns are equivalent:
# With commas
??,B5,??,B0,??,1C,??,20,??,43,??,99,??,4D,??,90,??,94,??,1C,??,92,??,91,??,68,??,26,??,23,??,21,??,A2,??,48,??,47
# With spaces
?? B5 ?? B0 ?? 1C ?? 20 ?? 43 ?? 99 ?? 4D ?? 90 ?? 94 ?? 1C ?? 92 ?? 91 ?? 68 ?? 26 ?? 23 ?? 21 ?? A2 ?? 48 ?? 47
# With spaces by 2 bytes groups
??B5 ??B0 ??1C ??20 ??43 ??99 ??4D ??90 ??94 ??1C ??92 ??91 ??68 ??26 ??23 ??21 ??A2 ??48 ??47
# Without any separators
??B5??B0??1C??20??43??99??4D??90??94??1C??92??91??68??26??23??21??A2??48??47
Apply some correction value to the found offset.
Syntax:
pattern + offsetCorrector
pattern - offsetCorrector
For example:
# offsetCorrector value is always in HEX.
# For e.g.: 20 and 0x20 are equal.
B801C4E10200A0E30000C1E5B601D4E11040BDE8??????EA + 20
Steps:
- Pattern
B801C4E10200A0E30000C1E5B601D4E11040BDE8??????EA
found at 0xA009B780 - Result is
0xA009B780 + 0x20 = 0xA009B7A0
Decoding a pointer value from the bytes found by the pattern.
Syntax:
*( subPattern )
*( subPattern ) + valueCorrector
*( subPattern ) - valueCorrector
For example:
# valueCorrector value is always in HEX.
# For e.g.: 20 and 0x20 are equal.
*(B801C4E10200A0E30000C1E5B601D4E11040BDE8??????EA + 20) + 2
Steps:
- Pattern
B801C4E10200A0E30000C1E5B601D4E11040BDE8??????EA+20
found at 0xA009B7A0 - Decoding bytes as pointer at 0xA009B7A0:
A009B7A0: CC 5B D9 A8 ; 0xA8D95BCC
- Result is
0xA8D95BCC + 0x2 = 0xA8D95BCE
Emulating ARM/THUMB LDR Rd, [PC, #offset]
instruction found by the pattern.
Syntax:
&( subPattern )
&( subPattern ) + valueCorrector
&( subPattern ) - valueCorrector
For example:
&( ??,48,??,47,??,B5,??,B0,??,1C,??,D1,??,20 ) + 0x4
Steps:
-
Pattern
??,48,??,47,??,B5,??,B0,??,1C,??,D1,??,20
found at 0xA093BA58 -
Emulating LDR on 0xA093BA58:
A093BA58: 37 48 ; ldr r0, [pc, #0xdc] ; Emulation: PC + 0xDC = 0xA093BB38
-
Decoding pointer at 0xA093BB38
A093BB38: 10 97 E6 A8 ; 0xA8E69710
-
Result is
0xA8E69710 + 0x4 = 0xA8E69714
Emulating ARM/THUMB B/BL/BLX
or LDR PC, [PC, #offset]
instructions found by the pattern.
Syntax:
&BL( subPattern )
&BL( subPattern ) + valueCorrector
&BL( subPattern ) - valueCorrector
For example:
&BL( ?? ?? ?? [1111101.] 00 00 5? E3 ?? ?? 9F 05 08 40 B? 08 ?? ?? ?? 0A 08 80 B? E8 )
Steps:
-
Pattern
?? ?? ?? [1111101.] 00 00 5? E3 ?? ?? 9F 05 08 40 B? 08 ?? ?? ?? 0A 08 80 B? E8
found at 0xA06A09A4 -
Emulating BL on 0xA06A09A4:
A06A09A4: 7B D6 E7 FA ; BLX #0xA0096398
-
Result is
#0xA0096398 | 1
Follow the branch and checking it for a pattern.
Syntax:
# ARM B/BL/BLX or THUMB BL/BLX (4 bytes instruction)
{ subPattern }
_BLF(subPattern) # alias for { }
# THUMB B (2 bytes instruction)
[ subPattern ]
Supported instructions:
# ARM
B #offset
BL #offset
BLX #offset
LDR PC, [PC, #offset]
# THUMB
BL #offset
BLX #offset
For example:
?? 1C ?? 48 ?? B5 ?? 68 { ?? 1C ?? 68 ?? 68 ?? 2B ?? D0 ?? 68 [ ?? 23 [ ?? B5 ?? 1C ?? 6E ] ] 47 } BD + 0x1
Steps:
- Pattern
?? 1C ?? 48 ?? B5 ?? 68 ?? ?? ?? ?? BD + 0x1
found at 0xA0978822A0978822: 01 1C ADD R1,R0,#0x0 A0978824: 62 48 LDR R0,[DAT_A09789B0] A0978826: 80 B5 PUSH {R7,LR} A0978828: 00 68 LDR R0,[R0,#0x0]=>DAT_A8DBE3F0 A097882A: 9E F0 F6 FD BL FUN_A0A1741A ; <--- see this A097882E: 80 BD POP {R7,PC}
- Emulating BL at 0xA097882A (+8)
A097882A: 9E F0 F6 FD ; BL #0xA0A1741A
- Checking pattern
?? 1C ?? 68 ?? 68 ?? 2B ?? D0 ?? 68 ?? ?? 47
at 0xA0A1741AA0A1741A: 0A 1C ADD R2,R1,#0x0 A0A1741C: 01 68 LDR R1,[R0,#0x0] A0A1741E: 8B 68 LDR R3,[R1,#0x8] A0A17420: 00 2B CMP R3,#0x0 A0A17422: 01 D0 BEQ LAB_A0A17428 A0A17424: C9 68 LDR R1,[R1,#0xC] A0A17426: F6 E7 B FUN_A0A17416 ; <--- see this A0A17428: 70 47 BX LR
- Emulating BL at 0xA0A17426 (+12)
A0A17426: F6 E7 ; B #0xA0A17416
- Checking pattern
?? 23 ?? ??
at 0xA0A17416A0A17416: 01 23 MOV R3,#0x1 A0A17418: D7 E7 B LAB_A0A173CA ; <--- see this
- Emulating BL at 0xA0A17418 (+2)
A0A17418: D7 E7 ; B #0xA0A173CA
- Checking pattern
?? B5 ?? 1C ?? 6E
at 0xA0A173CAA0A173CA: F8 B5 PUSH {R3,R4,R5,R6,R7,LR} A0A173CC: 04 1C ADD R4,R0,#0x0 A0A173CE: 80 6E LDR R0,[R0,#0x68] A0A173D0: 0D 1C ADD R5,R1,#0x0 A0A173D2: 16 1C ADD R6,R2,#0x0
- Pattern result is
0xA0978822 + 0x1 = 0xA0978823
Follow the reference and checking it for a pattern.
Syntax:
# ARM LDR (4 bytes instruction)
LDR{ subPattern }
# THUMB LDR (2 bytes instruction)
LDR[ subPattern ]
Supported instructions:
# ARM/THUMB
LDR Rd, [PC, #offset]
For example:
LDR{ 436f70797269676874204d47432032303034 } 1e ff 2f e1
Steps:
- Pattern
?? ?? ?? ?? 1e ff 2f e1
found at 0xA00A0B1C - Emulating LDR at 0xA00A0B1C (+0)
A00A0B1C: 00 00 9F E5 LDR R0, [PC, #+0x0] ; 0xA00A0B24 ; Emulation: PC + 0x0 = 0xA00A0B24
- Decoding pointer at 0xA00A0B24
A00A0B24: 1D 34 0A A0 ; 0xA00A341D
- Checking pattern
436f70797269676874204d47432032303034
at 0xA00A341DA00A341D: ds "Copyright MGC 2004 - Nucleus PLUS - Integrator RVCT v. 1.15"
- Result is:
0xA0A63270
If the found address points to a THUMB PUSH { ... }
instruction, +1 will be added to the result.
Example:
??,06,??,0E,??,38,??,30,??,78,??,42,??,D0,??,29,??,D1,??,42,??,D0,??,20,??,47
Steps:
- Pattern
F0B5061C0C1C151C85B068461122??49??????????E0207869466A460009085C307021780134
found at 0xA058BB98A058BB98 F0 B5 PUSH {R4,R5,R6,R7,LR} ; <-- see this A058BB9A 06 1C ADD R6,R0,#0x0 A058BB9C 0C 1C ADD R4,R1,#0x0 A058BB9E 15 1C ADD R5,R2,#0x0 A058BBA0 85 B0 SUB SP,#0x14 A058BBA2 68 46 MOV R0,SP A058BBA4 11 22 MOV R2,#0x11
- Result is:
0xA058BB98 | 1 = 0xA058BB99
Usually used in patterns.ini
for stub entries.
# Pattern result is 0xA8000000
< A8000000 >