diff --git a/lldbinit.py b/lldbinit.py
index 77fbe00..c4e31ac 100644
--- a/lldbinit.py
+++ b/lldbinit.py
@@ -62,19 +62,20 @@
if __name__ == "__main__":
print("Run only as script from LLDB... Not as standalone program!")
-import lldb
-import sys
-import re
+import argparse
+import fcntl
+import hashlib
+import json
import os
-import time
+import re
import struct
-import argparse
import subprocess
+import sys
import tempfile
import termios
-import fcntl
-import json
-import hashlib
+import time
+
+import lldb
try:
import keystone
@@ -220,9 +221,9 @@
"r8": 0, "r9": 0, "r10": 0, "r11": 0, "r12": 0, "r13": 0, "r14": 0, "r15": 0,
"rflags": 0, "cs": 0, "fs": 0, "gs": 0 }
-old_arm64 = { "x0": 0, "x1": 0, "x2": 0, "x3": 0, "x4": 0, "x5": 0, "x6": 0, "x7": 0, "x8": 0, "x9": 0, "x10": 0,
- "x11": 0, "x12": 0, "x13": 0, "x14": 0, "x15": 0, "x16": 0, "x17": 0, "x18": 0, "x19": 0, "x20": 0,
- "x21": 0, "x22": 0, "x23": 0, "x24": 0, "x25": 0, "x26": 0, "x27": 0, "x28": 0, "fp": 0, "lr": 0,
+old_arm64 = { "x0": 0, "x1": 0, "x2": 0, "x3": 0, "x4": 0, "x5": 0, "x6": 0, "x7": 0, "x8": 0, "x9": 0, "x10": 0,
+ "x11": 0, "x12": 0, "x13": 0, "x14": 0, "x15": 0, "x16": 0, "x17": 0, "x18": 0, "x19": 0, "x20": 0,
+ "x21": 0, "x22": 0, "x23": 0, "x24": 0, "x25": 0, "x26": 0, "x27": 0, "x28": 0, "fp": 0, "lr": 0,
"sp": 0, "pc": 0, "cpsr": 0 }
GlobalListOutput = []
@@ -240,7 +241,7 @@
g_dbdata = {}
# dyld modes
-dyld_mode_dict = {
+dyld_mode_dict = {
0: "dyld_image_adding",
1: "dyld_image_removing",
2: "dyld_image_info_change",
@@ -281,7 +282,7 @@ def __lldb_init_module(debugger, internal_dict):
if g_home == "":
g_home = os.getenv('HOME')
-
+
res = lldb.SBCommandReturnObject()
ci = debugger.GetCommandInterpreter()
@@ -354,6 +355,7 @@ def __lldb_init_module(debugger, internal_dict):
ci.HandleCommand("command script add -h '(lldbinit) Clear all module load breakpoints.' -f lldbinit.cmd_bmc bmc", res)
ci.HandleCommand("command script add -h '(lldbinit) List all on module load breakpoints.' -f lldbinit.cmd_bml bml", res)
ci.HandleCommand("command script add -h '(lldbinit) Enable anti-anti-debugging measures.' -f lldbinit.cmd_antidebug antidebug", res)
+ ci.HandleCommand("command script add -h '(lldbinit) Enable anti-anti-debugging measures.' -f lldbinit.cmd_antidebug_syscall antidebug_syscall", res)
ci.HandleCommand("command script add -h '(lldbinit) Print all images available at gdb_image_notifier() breakpoint.' -f lldbinit.cmd_print_notifier_images print_images", res)
# disable a breakpoint or all
ci.HandleCommand("command script add -h '(lldbinit) Disable a breakpoint.' -f lldbinit.cmd_bpd bpd", res)
@@ -509,7 +511,7 @@ def get_lldb_version(debugger):
lldb_minor = int(lldb_versions_match.groups()[4])
return lldb_major, lldb_minor
-def cmd_banner(debugger,command,result,dict):
+def cmd_banner(debugger, command, result, dict):
lldbver = debugger.GetVersionString().split('\n')[0]
print(GREEN + "[+] Loaded lldbinit version " + VERSION + "." + BUILD + " @ " + lldbver + RESET)
@@ -518,7 +520,7 @@ def cmd_lldbinitcmds(debugger, command, result, dict):
help_table = [
[ "lldbinitcmds", "this command" ],
-
+
[ "----[ Settings ]----", ""],
[ "enable", "configure lldb and lldbinit options" ],
[ "disable", "configure lldb and lldbinit options" ],
@@ -526,7 +528,7 @@ def cmd_lldbinitcmds(debugger, command, result, dict):
[ "enablesolib/disablesolib", "enable/disable the stop on library load events" ],
[ "enableaslr/disableaslr", "enable/disable process ASLR" ],
[ "datawin", "set start address to display on data window" ],
-
+
[ "----[ Breakpoints ]----", ""],
[ "b", "breakpoint address" ],
[ "bpt", "set a temporary software breakpoint" ],
@@ -574,16 +576,16 @@ def cmd_lldbinitcmds(debugger, command, result, dict):
[ "x{0..28}", "shortcuts to modify ARM64 registers" ],
[ "cfa/cfc/cfd/cfi/cfo/cfp/cfs/cft/cfz", "change x86/x64 CPU flags" ],
[ "cfn/cfz/cfc/cfv", "change AArch64 CPU flags (NZCV register)"],
-
+
[ "----[ File headers ]----", ""],
[ "show_loadcmds", "show otool output of Mach-O load commands" ],
[ "show_header", "show otool output of Mach-O header" ],
-
+
[ "----[ Cracking ]----", ""],
[ "crack", "return from current function" ],
[ "crackcmd", "set a breakpoint and return from that function" ],
[ "crackcmd_noret", "set a breakpoint and set a register value. doesn't return from function" ],
-
+
[ "----[ Misc ]----", ""],
[ "iphone", "connect to debugserver running on iPhone" ],
@@ -794,7 +796,7 @@ def antidebug_callback_step1(frame, bp_loc, dict):
if frame is None:
return 0
-
+
target = get_target()
if is_x64():
src_reg = "rdi"
@@ -805,7 +807,7 @@ def antidebug_callback_step1(frame, bp_loc, dict):
else:
print("[-] error: unsupported architecture")
return 0
-
+
mib_addr = int(frame.FindRegister(src_reg).GetValue(), 16)
mib0 = get_process().ReadUnsignedFromMemory(mib_addr, 4, error)
@@ -928,10 +930,84 @@ def cmd_antidebug(debugger, command, result, dict):
print("[+] Enabled anti-anti-debugging measures")
break
+
+def antidebug_syscall_callback(frame, bp_loc, dict):
+ SYSCALL_PTRACE = 0x200001a
+ PT_DENY_ATTACH = 0x1f
+ error = lldb.SBError()
+ if is_x64():
+ pc_reg = "rip"
+ arg_val = get_gp_register("rdi")
+ syscall_num = get_gp_register("rax")
+ elif is_arm():
+ pc_reg = "pc"
+ arg_val = get_gp_register("x0")
+ syscall_num = get_gp_register("x16")
+
+ if syscall_num == SYSCALL_PTRACE and arg_val == PT_DENY_ATTACH:
+ print("[+] Hit syscall/svc anti-debug request")
+ # Jump to next instruction address
+ cur_addr = get_gp_register(pc_reg)
+ next_addr = cur_addr + get_inst_size(cur_addr)
+ result = frame.registers[0].GetChildMemberWithName(pc_reg).SetValueFromCString(str(next_addr), error)
+ if not result:
+ print("[-] error: failed to write to {} register".format(pc_reg))
+ return 0
+ get_process().Continue()
+
+
+def cmd_antidebug_syscall(debugger, command, result, dict):
+ '''Enable anti-anti-debugging syscall. Use \'antidebug_syscall help\' for more information.'''
+ help = """
+Enable anti-anti-debugging measures for syscall/svc.
+Bypasses debugger detection via syscall (x64) / svc (ARM).
+
+Syntax: antidebug_syscall
+"""
+ cmd = command.split()
+ if len(cmd) > 0 and cmd[0] == "help":
+ print(help)
+ return
+
+ target = get_target()
+ loaded_program = target.modules[0]
+ for segment in loaded_program.section_iter():
+ if segment.GetName() == "__TEXT":
+ text_segment = segment
+ break
+
+ text_section = text_segment.FindSubSection("__text")
+ section_start = text_section.GetLoadAddress(target)
+ section_end = section_start + text_section.GetByteSize()
+ if DEBUG:
+ print("section_start: 0x{:x}".format(section_start))
+ print("section_end: 0x{:x}".format(section_end))
+
+ cur_addr = section_start
+ if is_x64():
+ syscall_mnemonic = "syscall"
+ elif is_arm():
+ syscall_mnemonic = "svc"
+
+ while cur_addr < section_end:
+ inst = get_mnemonic(cur_addr)
+ op = get_operands(cur_addr)
+ if DEBUG:
+ print("inst: {}, op: {}".format(inst, op))
+
+ if inst == syscall_mnemonic:
+ if is_arm() and op != "#0":
+ continue
+ print("[+] Found {} at: 0x{:x}".format(inst, cur_addr))
+ bp = target.BreakpointCreateByAddress(cur_addr)
+ bp.SetScriptCallbackFunction("lldbinit.antidebug_syscall_callback")
+ cur_addr += get_inst_size(cur_addr)
+
+
# the callback for the specific module loaded breakpoint
# supports x64, i386, arm64
def module_breakpoint_callback(frame, bp_loc, dict):
- global modules_list
+ global modules_list
# rdx contains the module address
# rdx+8 contains pointer to the module name string
if frame is None:
@@ -1077,7 +1153,7 @@ def cmd_bm(debugger, command, result, dict):
name = symbol.GetMangledName()
# XXX: improve this because we are doubling the amount of work?
# the lldb symbol isn't mangled
- name2 = symbol.GetName()
+ name2 = symbol.GetName()
if name == "_ZL18gdb_image_notifier15dyld_image_modejPK15dyld_image_info" or name2 == "lldb_image_notifier":
saddr = symbol.GetStartAddress()
# process needs to be loaded before we can execute this command...
@@ -1380,11 +1456,11 @@ def cmd_bpc(debugger, command, result, dict):
Syntax: bpc
-Notes:
+Notes:
- Only breakpoint numbers are valid, not addresses. Use \'bpl\' to list breakpoints.
- Expressions are supported, do not use spaces between operators.
"""
-
+
cmd = command.split()
if len(cmd) != 1:
print("[-] error: please insert a breakpoint number.")
@@ -1467,8 +1543,8 @@ def cmd_bpda(debugger, command, result, dict):
cmd = command.split()
if len(cmd) != 0:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
print("[-] error: command doesn't take any arguments.")
print("")
print(help)
@@ -1531,8 +1607,8 @@ def cmd_bpea(debugger, command, result, dict):
cmd = command.split()
if len(cmd) != 0:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
print("[-] error: command doesn't take any arguments.")
print("")
print(help)
@@ -1557,8 +1633,8 @@ def cmd_bpl(debugger, command, result, dict):
cmd = command.split()
if len(cmd) != 0:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
print("[-] error: command doesn't take any arguments.")
print("")
print(help)
@@ -1627,8 +1703,8 @@ def cmd_skip(debugger, command, result, dict):
cmd = command.split()
if len(cmd) != 0:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
print("[-] error: command doesn't take any arguments.")
print("")
print(help)
@@ -1673,8 +1749,8 @@ def cmd_int3(debugger, command, result, dict):
return
elif len(cmd) == 1:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
int3_addr = evaluate(cmd[0])
if int3_addr is None:
@@ -1702,14 +1778,14 @@ def cmd_int3(debugger, command, result, dict):
patch_bytes = str('\xCC')
if is_arm():
# brk #0
- patch_bytes = str("\x00\x00\x20\xd4")
+ patch_bytes = str("\x00\x00\x20\xd4")
else:
patch_bytes = bytearray(b'\xCC')
if is_arm():
patch_bytes = bytearray(b'\x00\x00\x20\xd4')
# insert the patch
- result = target.GetProcess().WriteMemory(int3_addr, patch_bytes, error)
+ result = target.GetProcess().WriteMemory(int3_addr, patch_bytes, error)
# XXX: compare len(patch) with result
if not error.Success():
print("[-] error: Failed to write memory at 0x{:x}.".format(int3_addr))
@@ -1743,14 +1819,14 @@ def cmd_rint3(debugger, command, result, dict):
return
elif len(cmd) == 1:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
int3_addr = evaluate(cmd[0])
if int3_addr is None:
print("[-] error: invalid input address value.")
print("")
print(help)
- return
+ return
else:
print("[-] error: please insert a breakpoint patched address.")
print("")
@@ -1808,8 +1884,8 @@ def cmd_listint3(debugger, command, result, dict):
cmd = command.split()
if len(cmd) != 0:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
print("[-] error: command doesn't take any arguments.")
print("")
print(help)
@@ -1843,8 +1919,8 @@ def cmd_nop(debugger, command, result, dict):
cmd = command.split()
if len(cmd) == 1:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
nop_addr = evaluate(cmd[0])
patch_size = 1
@@ -1916,8 +1992,8 @@ def cmd_null(debugger, command, result, dict):
cmd = command.split()
if len(cmd) == 1:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
null_addr = evaluate(cmd[0])
patch_size = 1
if null_addr is None:
@@ -1963,7 +2039,7 @@ def cmd_stepo(debugger, command, result, dict):
"""Step over calls and some other instructions so we don't need to step into them. Use \'stepo help\' for more information."""
help = """
Step over calls and loops that we want executed but not step into.
-Affected instructions:
+Affected instructions:
- x86: call, movs, stos, cmps, loop.
- arm64: bl, blr, blraa, blraaz, blrab, blrabz.
@@ -2027,8 +2103,8 @@ def cmd_bpn(debugger, command, result, dict):
cmd = command.split()
if len(cmd) != 0:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
print("[-] error: command doesn't take any arguments.")
print("")
print(help)
@@ -2121,7 +2197,7 @@ def cmd_crackcmd(debugger, command, result, dict):
print("[-] error: please check required arguments.")
print("")
print(help)
- return
+ return
# XXX: is there a way to verify if address is valid? or just let lldb error when setting the breakpoint
address = evaluate(cmd[0])
@@ -2321,8 +2397,8 @@ def cmd_db(debugger, command, result, dict):
return
elif len(cmd) == 1:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
dump_addr = evaluate(cmd[0])
if dump_addr is None:
print("[-] error: invalid address value.")
@@ -2331,15 +2407,15 @@ def cmd_db(debugger, command, result, dict):
return
elif len(cmd) == 2:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
dump_addr = evaluate(cmd[0])
if dump_addr is None:
print("[-] error: invalid address value.")
print("")
print(help)
return
- size = evaluate(cmd[1])
+ size = evaluate(cmd[1])
if size is None:
print("[-] error: invalid size value.")
print("")
@@ -2427,8 +2503,8 @@ def cmd_dw(debugger, command, result, dict):
return
elif len(cmd) == 1:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
dump_addr = evaluate(cmd[0])
if dump_addr is None:
print("[-] error: invalid address value.")
@@ -2437,15 +2513,15 @@ def cmd_dw(debugger, command, result, dict):
return
elif len(cmd) == 2:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
dump_addr = evaluate(cmd[0])
if dump_addr is None:
print("[-] error: invalid address value.")
print("")
print(help)
return
- size = evaluate(cmd[1])
+ size = evaluate(cmd[1])
if size is None:
print("[-] error: invalid size value.")
print("")
@@ -2461,7 +2537,7 @@ def cmd_dw(debugger, command, result, dict):
print("[-] size must be multiple of 16 bytes.")
return
- err = lldb.SBError()
+ err = lldb.SBError()
membuf = get_process().ReadMemory(dump_addr, size, err)
if not err.Success():
print("[-] error: failed to read memory from address 0x{:x}".format(dump_addr))
@@ -2517,8 +2593,8 @@ def cmd_dd(debugger, command, result, dict):
return
elif len(cmd) == 1:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
dump_addr = evaluate(cmd[0])
if dump_addr is None:
print("[-] error: invalid address value.")
@@ -2527,15 +2603,15 @@ def cmd_dd(debugger, command, result, dict):
return
elif len(cmd) == 2:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
dump_addr = evaluate(cmd[0])
if dump_addr is None:
print("[-] error: invalid address value.")
print("")
print(help)
return
- size = evaluate(cmd[1])
+ size = evaluate(cmd[1])
if size is None:
print("[-] error: invalid size value.")
print("")
@@ -2605,8 +2681,8 @@ def cmd_dq(debugger, command, result, dict):
return
elif len(cmd) == 1:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
dump_addr = evaluate(cmd[0])
if dump_addr is None:
print("[-] error: invalid address value.")
@@ -2615,15 +2691,15 @@ def cmd_dq(debugger, command, result, dict):
return
elif len(cmd) == 2:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
dump_addr = evaluate(cmd[0])
if dump_addr is None:
print("[-] error: invalid address value.")
print("")
print(help)
return
- size = evaluate(cmd[1])
+ size = evaluate(cmd[1])
if size is None:
print("[-] error: invalid size value.")
print("")
@@ -2658,7 +2734,7 @@ def cmd_dq(debugger, command, result, dict):
(mem0, mem1, mem2, mem3) = struct.unpack("QQQQ", membuf[index:index+0x20])
szaddr = "0x%.016lX" % dump_addr
if POINTER_SIZE == 4:
- szaddr = "0x%.08X" % dump_addr
+ szaddr = "0x%.08X" % dump_addr
data_str = COLOR_HEXDUMP_DATA + " {:016x} {:016x} {:016x} {:016x} ".format(mem0, mem1, mem2, mem3) + RESET
output(BOLD + COLOR_HEXDUMP_ADDR + "{:s} :".format(szaddr) + RESET + data_str + BOLD + COLOR_HEXDUMP_ASCII + "{:s}".format(quotechars(membuf[index:index+0x20])) + RESET)
if index + 0x20 != size:
@@ -2699,7 +2775,7 @@ def quotechars( chars ):
for x in bytearray(chars):
if x >= 0x20 and x <= 0x7E:
data += chr(x)
- else:
+ else:
data += "."
return data
@@ -3929,7 +4005,7 @@ def regarm64():
output(linefmt.format(flags, reason) + "\n")
def print_registers():
- if is_i386():
+ if is_i386():
reg32()
elif is_x64():
reg64()
@@ -4069,7 +4145,7 @@ def disassemble(start_address, nrlines):
max_mnem_size = 0
for i in instructions_mem:
if i.size > max_size:
- max_size = i.size
+ max_size = i.size
mnem_len = len(i.GetMnemonic(target))
if mnem_len > max_mnem_size:
max_mnem_size = mnem_len
@@ -4098,7 +4174,7 @@ def disassemble(start_address, nrlines):
if CONFIG_ENABLE_COLOR == 1:
output(COLOR_SYMBOL_NAME + "@ {}:".format(module_name) + "\n" + RESET)
else:
- output("@ {}:".format(module_name) + "\n")
+ output("@ {}:".format(module_name) + "\n")
elif symbol_name is not None:
# print the first time there is a symbol name and save its interval
# so we don't print again until there is a different symbol
@@ -4238,14 +4314,14 @@ def cmd_show_loadcmds(debugger, command, result, dict):
cmd = command.split()
if len(cmd) == 1:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
header_addr = evaluate(cmd[0])
if header_addr is None:
print("[-] error: invalid header address value.")
print("")
print(help)
- return
+ return
else:
print("[-] error: please insert a valid Mach-O header address.")
print("")
@@ -4289,14 +4365,14 @@ def cmd_show_header(debugger, command, result, dict):
cmd = command.split()
if len(cmd) == 1:
if cmd[0] == "help":
- print(help)
- return
+ print(help)
+ return
header_addr = evaluate(cmd[0])
if header_addr is None:
print("[-] error: invalid header address value.")
print("")
print(help)
- return
+ return
else:
print("[-] error: please insert a valid Mach-O header address.")
print("")
@@ -4370,9 +4446,9 @@ def cmd_asm32(debugger, command, result, dict):
inst_list = []
while True:
try:
- line = raw_input('Assemble ("stop" or "end" to finish): ')
+ line = raw_input('Assemble ("stop" or "end" to finish): ')
except NameError:
- line = input('Assemble ("stop" or "end" to finish): ')
+ line = input('Assemble ("stop" or "end" to finish): ')
if line == 'stop' or line == 'end':
break
inst_list.append(line)
@@ -4403,9 +4479,9 @@ def cmd_asm64(debugger, command, result, dict):
inst_list = []
while True:
try:
- line = raw_input('Assemble ("stop" or "end" to finish): ')
+ line = raw_input('Assemble ("stop" or "end" to finish): ')
except NameError:
- line = input('Assemble ("stop" or "end" to finish): ')
+ line = input('Assemble ("stop" or "end" to finish): ')
if line == 'stop' or line == 'end':
break
inst_list.append(line)
@@ -4421,7 +4497,7 @@ def cmd_arm32(debugger, command, result, dict):
Type one instruction per line. Finish with \'end\' or \'stop\'.
Keystone set to KS_ARCH_ARM and KS_MODE_ARM.
-
+
Requires Keystone and Python bindings from www.keystone-engine.org.
"""
cmd = command.split()
@@ -4436,9 +4512,9 @@ def cmd_arm32(debugger, command, result, dict):
inst_list = []
while True:
try:
- line = raw_input('Assemble ("stop" or "end" to finish): ')
+ line = raw_input('Assemble ("stop" or "end" to finish): ')
except NameError:
- line = input('Assemble ("stop" or "end" to finish): ')
+ line = input('Assemble ("stop" or "end" to finish): ')
if line == 'stop' or line == 'end':
break
inst_list.append(line)
@@ -4469,9 +4545,9 @@ def cmd_armthumb(debugger, command, result, dict):
inst_list = []
while True:
try:
- line = raw_input('Assemble ("stop" or "end" to finish): ')
+ line = raw_input('Assemble ("stop" or "end" to finish): ')
except NameError:
- line = input('Assemble ("stop" or "end" to finish): ')
+ line = input('Assemble ("stop" or "end" to finish): ')
if line == 'stop' or line == 'end':
break
inst_list.append(line)
@@ -4502,9 +4578,9 @@ def cmd_arm64(debugger, command, result, dict):
inst_list = []
while True:
try:
- line = raw_input('Assemble ("stop" or "end" to finish): ')
+ line = raw_input('Assemble ("stop" or "end" to finish): ')
except NameError:
- line = input('Assemble ("stop" or "end" to finish): ')
+ line = input('Assemble ("stop" or "end" to finish): ')
if line == 'stop' or line == 'end':
break
inst_list.append(line)
@@ -4512,7 +4588,7 @@ def cmd_arm64(debugger, command, result, dict):
assemble_keystone(keystone.KS_ARCH_ARM64, keystone.KS_MODE_ARM, inst_list)
# XXX: help
-def cmd_IphoneConnect(debugger, command, result, dict):
+def cmd_IphoneConnect(debugger, command, result, dict):
'''Connect to debugserver running on iPhone.'''
help = """ """
global GlobalListOutput
@@ -4887,7 +4963,7 @@ def cmd_fixret(debugger, command, result, dict):
rsp = rsp + 0x8
get_frame().reg["rsp"].value = format(rsp, '#x')
if len(cmd) == 0:
- get_process().Continue()
+ get_process().Continue()
# return the module to which an address belongs to
# XXX: duplicate of get_module_name()
@@ -4967,7 +5043,7 @@ def cmd_addcomment(debugger, command, result, dict):
# XXX: is there a better solution here?
comment = ' '.join([str(item) for item in cmd[1:]])
- if found is None:
+ if found is None:
g_dbdata["comments"].append({
"offset": hex(offset), # always from the base address of the module
"text": comment,
@@ -5133,13 +5209,13 @@ def cmd_save_session(debugger, command, result, dict):
# for dyld we obtain an address without the base
# for an object we obtain the full base address without aslr
# we should just store offset to the image and then restore using current information
- target = get_target()
+ target = get_target()
# list all current breakpoints and store them
for bpt in target.breakpoint_iter():
# XXX: we need to iterate all locations of each breakpoint... geezzzzzz
loc = bpt.location
# for item in bpt.locations:
- item = loc[0]
+ item = loc[0]
# if the address belongs nowhere this will be an invalid object so nothing to do here
if item is None:
continue
@@ -5378,14 +5454,14 @@ def cmd_run(debugger, command, result, dict):
"""
# reset internal state variables
- res = lldb.SBCommandReturnObject()
+ res = lldb.SBCommandReturnObject()
# must be set to true otherwise we don't get any output on the first stop hook related to this
debugger.SetAsync(True)
# imitate the original 'r' alias plus the stop at entry and pass everything else as target argv[]
debugger.GetCommandInterpreter().HandleCommand("process launch -s -X true -- {}".format(command), res)
#------------------------------------------------------------
-# The heart of lldbinit - when lldb stop this is where we land
+# The heart of lldbinit - when lldb stop this is where we land
#------------------------------------------------------------
def HandleProcessLaunchHook(debugger, command, result, dict):
@@ -5455,7 +5531,7 @@ def HandleHookStopOnTarget(debugger, command, result, dict):
# load for a known target
if os.path.exists(g_db):
with open(g_db, 'r') as f:
- g_dbdata = json.load(f)
+ g_dbdata = json.load(f)
if DEBUG:
print(g_dbdata)
# check if hashes match
@@ -5508,7 +5584,7 @@ def HandleHookStopOnTarget(debugger, command, result, dict):
return
frame = get_frame()
- if not frame:
+ if not frame:
return
# XXX: this has a small bug - if we reload the script and try commands that depend on POINTER_SIZE
diff --git a/tests/Makefile b/tests/Makefile
index c2a3b0a..bbeee7e 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -6,7 +6,8 @@ all:
$(CC) ptrace.c -o ptrace
$(CC) taskget.c -o taskget
$(CC) taskset.c -o taskset
+ $(CC) -framework Foundation syscall.m -o syscall
.PHONY: clean
clean:
- rm -f sysctl ptrace taskget taskset
+ rm -f sysctl ptrace taskget taskset syscall
diff --git a/tests/syscall.m b/tests/syscall.m
new file mode 100644
index 0000000..e31c325
--- /dev/null
+++ b/tests/syscall.m
@@ -0,0 +1,40 @@
+//
+// https://cardaci.xyz/blog/2018/02/12/a-macos-anti-debug-technique-using-ptrace/
+// $ clang -framework Foundation syscall.m -o syscall
+//
+// ref 1: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/kern/syscalls.master
+// ref 2: https://opensource.apple.com/source/xnu/xnu-7195.81.3/osfmk/mach/i386/syscall_sw.h.auto.html
+//
+
+#import
+
+@interface Foo : NSObject
+@end
+
+@implementation Foo
+
++(void)load {
+ NSLog (@"-- LOAD");
+
+#if TARGET_CPU_X86_64
+ asm("movq $0, %rcx");
+ asm("movq $0, %rdx");
+ asm("movq $0, %rsi");
+ asm("movq $0x1f, %rdi"); /* PT_DENY_ATTACH 31 (0x1f)*/
+ asm("movq $0x200001a, %rax"); /* ptrace syscall number 26 (0x1a) */
+ /* The syscall number for ptrace is 0x1a, but by definition in syscall_sw.h, 0x200001a must be set. */
+ asm("syscall");
+#elif TARGET_CPU_ARM64
+ asm("mov X0, #0x1f"); /* PT_DENY_ATTACH 31 (0x1f)*/
+ asm("movz X16, #0x001a"); /* ptrace syscall number 26 (0x1a) */
+ asm("movk X16, #0x0200, lsl #16"); /* The syscall number for ptrace is 0x1a, but by definition in syscall_sw.h, 0x200001a must be set. */
+ asm("svc 0");
+#endif
+}
+
+@end
+
+int main (int argc, const char * argv[]) {
+ NSLog (@"-- MAIN");
+ return 0;
+}