(12345)₁₀ = (3039)₁₆
- When 12345 is divided by 16, the quotient is 771 and the remainder is 9.
- When 771 is divided by 16, the quotient is 48 and the remainder is 3.
- When 48 is divided by 16, the quotient is 3 and the remainder is 0.
- When 3 is divided by 16, the quotient is 0 and the remainder is 3.
- Write the remainders from bottom to top.
(3039)₁₆ = (3 × 16³) + (0 × 16²) + (3 × 16¹) + (9 × 16⁰) = (12345)₁₀
The 0x prefix must be added explicitly
# dec to hex
$ printf '0x%x\n' 12345
0x3039
# hex to dec
$ printf '%d\n' 0x3039
12345
# shell math, note the result is always dec
$ echo $(( 1+17 ))
18
$ echo $(( 0x1+17 ))
18
$ echo $(( 0x1 + 0x11 ))
18
check the architecture you have
$ uname -m
x86_64
chech type of file
$ file alert.app/Contents/MacOS/alert
alert.app/Contents/MacOS/alert: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64:Mach-O 64-bit executable arm64]
alert.app/Contents/MacOS/alert (for architecture x86_64): Mach-O 64-bit executable x86_64
alert.app/Contents/MacOS/alert (for architecture arm64): Mach-O 64-bit executable arm64
So it is a fat binary what contains several architectures - x86_64 and arm64
$ otool -fh alert.app/Contents/MacOS/alert
Fat headers
fat_magic 0xcafebabe
nfat_arch 2
architecture 0
cputype 16777223
cpusubtype 3
capabilities 0x0
offset 16384
size 58720
align 2^14 (16384)
architecture 1
cputype 16777228
cpusubtype 0
capabilities 0x0
offset 81920
size 73072
align 2^14 (16384)
alert.app/Contents/MacOS/alert:
Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
0xfeedfacf 16777223 3 0x00 2 37 4216 0x00200085
$ size alert.app/Contents/MacOS/alert
__TEXT __DATA __OBJC others dec hex
16384 16384 0 4295000064 4295032832 100010000
display the load commands:
$ otool -l alert.app/Contents/MacOS/alert
...long output...
print shared libraries used
$ otool -L alert.app/Contents/MacOS/alert
alert.app/Contents/MacOS/alert:
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1775.118.101)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.100.5)
/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 2022.44.149)
@rpath/libswiftAppKit.dylib (compatibility version 1.0.0, current version 104.0.0)
...
list symbols from object files
$ nm alert.app/Contents/MacOS/alert
...long output...
Check disassembly
# limited to first 10 lines
$ otool -tVj -arch x86_64 -function_offsets alert | head -10
alert:
(__TEXT,__text) section
+0 0000000100001920 55 pushq %rbp
+1 0000000100001921 4889e5 movq %rsp, %rbp
+4 0000000100001924 53 pushq %rbx
+5 0000000100001925 50 pushq %rax
+6 0000000100001926 488b3d5b2d0000 movq 0x2d5b(%rip), %rdi ## Objc class ref: _OBJC_CLASS_$_NSApplication
+13 000000010000192d e8ca160000 callq 0x100002ffc ## symbol stub for: _swift_getInitializedObjCClass
+18 0000000100001932 488b35ff2c0000 movq 0x2cff(%rip), %rsi ## Objc selector ref: sharedApplication
+25 0000000100001939 4889c7 movq %rax, %rdi
...
hex it!
# print bytes form position 0 to 0+120 by 16 bytes in a row
$ xxd -s 0 -l 120 -c 16 alert
00000000: cafe babe 0000 0002 0100 0007 0000 0003 ................
00000010: 0000 4000 0000 e560 0000 000e 0100 000c ..@....`........
00000020: 0000 0000 0001 4000 0001 1d70 0000 000e [email protected]....
00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000070: 0000 0000 0000 0000 ........
Note,
00000000: cafe babe
means Universal fat Binary archive - Big Endian.
cefaedfe: Mach-O Little Endian (32-bit)
cffaedfe: Mach-O Little Endian (64-bit)
feedface: Mach-O Big Endian (32-bit)
feedfacf: Mach-O Big Endian (64-bit)
let's get hexdecimal of the exact line +6 0000000100001926 488b3d5b2d0000 movq 0x2d5b(%rip), %rdi
First get architecture offset
$ lipo -detailed_info alert
Fat header in: alert
fat_magic 0xcafebabe
nfat_arch 2
architecture x86_64
cputype CPU_TYPE_X86_64
cpusubtype CPU_SUBTYPE_X86_64_ALL
capabilities 0x0
offset 16384 < = = = = = = same as otool -fh
size 58720
align 2^14 (16384)
architecture arm64
cputype CPU_TYPE_ARM64
cpusubtype CPU_SUBTYPE_ARM64_ALL
capabilities 0x0
offset 81920
size 73072
align 2^14 (16384)
as example for Non-fat:
$ lipo -detailed_info skype
input file skype is not a fat file
Non-fat file: skype is architecture: x86_64
Get section info
$ otool -l -arch x86_64 alert | grep __text -A 5
sectname __text
segname __TEXT
addr 0x0000000100001920
size 0x000000000000160a
offset 6432
align 2^4 (16)
- address = 0000000100001926
- segment.address = 0x0000000100001920 (addr)
- segment.offset = 6432
- fat_arch.offset = 16384
offset = 0x5926
$ printf '0x%x\n' $(( 0x0000000100001926 - 0x0000000100001920 + 6432 + 16384))
0x5926
$ xxd -s 0x5926 -l 120 -c 16 alert
00005926: 488b 3d5b 2d00 00e8 ca16 0000 488b 35ff H.=[-.......H.5.
00005936: 2c00 0048 89c7 e861 1600 0048 89c7 e865 ,..H...a...H...e
00005946: 1600 0048 8905 7836 0000 31ff e8b9 0100 ...H..x6..1.....
00005956: 0048 89c7 e831 1600 0048 8b35 da2c 0000 .H...1...H.5.,..
00005966: 4889 c7e8 3416 0000 4889 055b 3600 0048 H...4...H..[6..H
00005976: 8b3d 4c36 0000 488b 35c5 2c00 0048 89c2 .=L6..H.5.,..H..
00005986: e817 1600 00e8 b815 0000 89c3 e8ab 1500 ................
00005996: 0089 df48 89c6 e895 ...H....
Same for the other arch, but be aware that the bytes can be reversed LE<->BE
otool: +12 0000000100002c94 d503201f nop
; d503201f => 1f 20 03 d5
xxd: 00016c94: 1f20 03d5 80c2 0258 0d01 0094 1f20 03d5 . .....X..... ..
Dump method names from Obj-C section otool -oV alert