├── README.txt ├── lldbinit.py └── lldbinitpy3.py /README.txt: -------------------------------------------------------------------------------- 1 | Similar implementation of .gdbinit from fG! for lldb in python 2 | 3 | How to install it: 4 | cp lldbinit.py /Library/Python/2.7/site-packages 5 | in $HOME/.lldbinit add: 6 | command script import lldbinit 7 | 8 | Later versions of MacOS come with lldb and Python3 which is bundled with Xcode. 9 | Thus to install python3 version on later versions: 10 | cp lldbinitpy3.py ~/ 11 | in $HOME/.lldbinit add: 12 | command script import ~/lldbinitpy3.py 13 | 14 | If you want latest lldb, to compile it from svn we need to do: 15 | svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb 16 | xcodebuild -configuration Release 17 | 18 | Commands which are implemented: 19 | stepo - step over some instructions (call/movs/stos/cmps/loop) 20 | dd - dump hex data at certain address (keep compatibility with .gdbinit) 21 | this shoud be db command 22 | db - same as dd for SoftICE enthusiasts 23 | ctx/context - dump registers and assembly 24 | lb - load breakpoints from file and apply them (currently only func names are applied) 25 | lb_rva - load breakpoints from file and apply to main executable, only RVA in this case 26 | and command will determine main program base and apply breaks 27 | u - dump instructions at certain address (SoftICE like u command style) 28 | ddword - dump data as dword 29 | dq - dump data as qword 30 | dw - dump data as word 31 | iphone - connect to debugserver running on iPhone 32 | findmem - command to search memory 33 | [options] 34 | -s searches for specified string 35 | -u searches for specified unicode string 36 | -b searches binary (eg. -b 4142434445 will find ABCDE anywhere in mem) 37 | -d searches dword (eg. -d 0x41414141) 38 | -q searches qword (eg. -d 0x4141414141414141) 39 | -f loads patern from file if it's tooooo big to fit into any of specified 40 | options 41 | -c specify if you want to find N occurances (default is all) 42 | bt - broken... and removed, now thread/frame information is by default shown on every 43 | hook-stop by lldb itself... 44 | 45 | hook-stop can be added only when target exists, before it's not possible (maybe in later versions 46 | of lldb it is or will be possible but...). Trick to get arround this is to create thread which will 47 | try to add hook-stop, and will continue doing so until it's done. This could cause some raise conditions 48 | as I don't know if this is thread safe, however in my testing (and using it) it worked quite well so 49 | I keep using it instead of adding extra command "init" or such when target is created... 50 | 51 | Currently registers dump are done for i386/x86_64/arm 52 | 53 | For supported ARM types for iPhone check here: 54 | source/Plugins/Platform/MacOSX/PlatformDarwin.cpp 55 | PlatformDarwin::ARMGetSupportedArchitectureAtIndex <-- maybe wrong, but you have 56 | idea what they support 57 | -------------------------------------------------------------------------------- /lldbinit.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Similar implementation of .gdbinit from fG! for lldb in python 3 | 4 | How to install it: 5 | cp lldbinit.py /Library/Python/2.7/site-packages 6 | in $HOME/.lldbinit add: 7 | command script import lldbinit 8 | 9 | If you want latest lldb, to compile it from svn we need to do: 10 | svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb 11 | xcodebuild -configuration Release 12 | 13 | Commands which are implemented: 14 | stepo - step over some instructions (call/movs/stos/cmps/loop) 15 | dd - dump hex data at certain address (keep compatibility with .gdbinit) 16 | this shoud be db command 17 | ctx/context - dump registers and assembly 18 | lb - load breakpoints from file and apply them (currently only func names are applied) 19 | lb_rva - load breakpoints from file and apply to main executable, only RVA in this case 20 | and command will determine main program base and apply breaks 21 | u - dump instructions at certain address (SoftICE like u command style) 22 | ddword - dump data as dword 23 | dq - dump data as qword 24 | dw - dump data as word 25 | iphone - connect to debugserver running on iPhone 26 | findmem - command to search memory 27 | [options] 28 | -s searches for specified string 29 | -u searches for specified unicode string 30 | -b searches binary (eg. -b 4142434445 will find ABCDE anywhere in mem) 31 | -d searches dword (eg. -d 0x41414141) 32 | -q searches qword (eg. -d 0x4141414141414141) 33 | -f loads patern from file if it's tooooo big to fit into any of specified 34 | options 35 | -c specify if you want to find N occurances (default is all) 36 | bt - broken... and removed, now thread/frame information is by default shown on every 37 | hook-stop by lldb itself... 38 | 39 | hook-stop can be added only when target exists, before it's not possible (maybe in later versions 40 | of lldb it is or will be possible but...). Trick to get arround this is to create thread which will 41 | try to add hook-stop, and will continue doing so until it's done. This could cause some raise conditions 42 | as I don't know if this is thread safe, however in my testing (and using it) it worked quite well so 43 | I keep using it instead of adding extra command "init" or such when target is created... 44 | 45 | Currently registers dump are done for i386/x86_64/arm 46 | 47 | For supported ARM types for iPhone check here: 48 | source/Plugins/Platform/MacOSX/PlatformDarwin.cpp 49 | PlatformDarwin::ARMGetSupportedArchitectureAtIndex <-- maybe wrong, but you have 50 | idea what they support 51 | 52 | ''' 53 | 54 | if __name__ == "__main__": 55 | print("Run only as script from lldb... Not as standalone program"); 56 | 57 | try: 58 | import lldb 59 | except: 60 | pass; 61 | import sys 62 | import re 63 | import os 64 | import thread 65 | import time 66 | import struct 67 | import argparse 68 | import subprocess 69 | 70 | old_eax = 0; 71 | old_ecx = 0; 72 | old_edx = 0; 73 | old_ebx = 0; 74 | old_esp = 0; 75 | old_ebp = 0; 76 | old_esi = 0; 77 | old_edi = 0; 78 | old_eip = 0; 79 | old_eflags = 0; 80 | old_cs = 0; 81 | old_ds = 0; 82 | old_fs = 0; 83 | old_gs = 0; 84 | old_ss = 0; 85 | old_es = 0; 86 | 87 | old_rax = 0; 88 | old_rcx = 0; 89 | old_rdx = 0; 90 | old_rbx = 0; 91 | old_rsp = 0; 92 | old_rbp = 0; 93 | old_rsi = 0; 94 | old_rdi = 0; 95 | old_r8 = 0; 96 | old_r9 = 0; 97 | old_r10 = 0; 98 | old_r11 = 0; 99 | old_r12 = 0; 100 | old_r13 = 0; 101 | old_r14 = 0; 102 | old_r15 = 0; 103 | old_rflags = 0; 104 | old_rip = 0; 105 | 106 | old_arm_r0 = 0; 107 | old_arm_r1 = 0; 108 | old_arm_r2 = 0; 109 | old_arm_r3 = 0; 110 | old_arm_r4 = 0; 111 | old_arm_r5 = 0; 112 | old_arm_r6 = 0; 113 | old_arm_r7 = 0; 114 | old_arm_r8 = 0; 115 | old_arm_r9 = 0; 116 | old_arm_r10 = 0; 117 | old_arm_r11 = 0; 118 | old_arm_r12 = 0; 119 | old_arm_sp = 0; 120 | old_arm_lr = 0; 121 | old_arm_pc = 0; 122 | old_arm_cpsr = 0; 123 | 124 | BLACK = 0 125 | RED = 1 126 | GREEN = 2 127 | YELLOW = 3 128 | BLUE = 4 129 | MAGENTA = 5 130 | CYAN = 6 131 | WHITE = 7 132 | 133 | COLOR_REGNAME = GREEN 134 | COLOR_REGVAL = WHITE 135 | COLOR_REGVAL_MODIFIED = RED 136 | COLOR_SEPARATOR = BLUE 137 | COLOR_CPUFLAGS = RED 138 | COLOR_HIGHLIGHT_LINE = CYAN 139 | 140 | arm_type = "thumbv7-apple-ios"; 141 | 142 | GlobalListOutput = []; 143 | 144 | hook_stop_added = 0; 145 | 146 | def wait_for_hook_stop(): 147 | while True: 148 | #print("Waiting..."); 149 | res = lldb.SBCommandReturnObject(); 150 | lldb.debugger.GetCommandInterpreter().HandleCommand("target stop-hook add -o \"HandleHookStopOnTarget\"", res); 151 | if res.Succeeded() == True: 152 | return; 153 | time.sleep(0.05); 154 | 155 | def __lldb_init_module(debugger, internal_dict): 156 | ''' we can execute commands using debugger.HandleCommand which makes all outptu to default 157 | lldb console. With GetCommandinterpreter().HandleCommand() we can consume all output 158 | with SBCommandReturnObject and parse data before we send it to output (eg. modify it); 159 | ''' 160 | global hook_stop_added; 161 | 162 | ''' 163 | If I'm running from $HOME where .lldbinit is located, seems like lldb will load 164 | .lldbinit 2 times, thus this dirty hack is here to prevent doulbe loading... 165 | if somebody knows better way, would be great to know :) 166 | ''' 167 | var = lldb.debugger.GetInternalVariableValue("stop-disassembly-count", lldb.debugger.GetInstanceName()); 168 | if var.IsValid(): 169 | var = var.GetStringAtIndex(0); 170 | if var == "0": 171 | return; 172 | res = lldb.SBCommandReturnObject(); 173 | 174 | lldb.debugger.GetCommandInterpreter().HandleCommand("settings set target.x86-disassembly-flavor intel", res); 175 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.stepo stepo", res); 176 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.HandleHookStopOnTarget HandleHookStopOnTarget", res); 177 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.dd dd", res); 178 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.si si", res); 179 | #lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.r r", res); 180 | #lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.r run", res); 181 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.HandleHookStopOnTarget ctx", res); 182 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.HandleHookStopOnTarget context", res); 183 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.DumpInstructions u", res); 184 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.LoadBreakPoints lb", res); 185 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.LoadBreakPointsRva lbrva", res); 186 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.dq dq", res); 187 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.ddword ddword", res); 188 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.dw dw", res); 189 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.IphoneConnect iphone", res); 190 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.findmem findmem", res); 191 | 192 | 193 | ''' 194 | target stop-hook can be added only when target is loaded, thus I create thread 195 | to execute this command until it returns success... dunno if this is ok, or thread 196 | safe, but I hate to add extra command "init" or such to install this hook... 197 | ''' 198 | thread.start_new_thread(wait_for_hook_stop, ()); 199 | 200 | #lldb.debugger.GetCommandInterpreter().HandleCommand("settings set prompt \"\033[01;31m(lldb) \033[0m\"", res); 201 | lldb.debugger.GetCommandInterpreter().HandleCommand("settings set stop-disassembly-count 0", res); 202 | return; 203 | 204 | 205 | def get_arch(): 206 | return lldb.debugger.GetSelectedTarget().triple.split('-')[0]; 207 | def get_frame(): 208 | #return lldb.debugger.GetSelectedTarget().process.selected_thread.GetSelectedFrame(); 209 | #return lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() 210 | #return lldb.debugger.GetTargetAtIndex(0).process.selected_thread.GetFrameAtIndex(0); 211 | 212 | #return frame for stopped thread... there should be one at least... 213 | ret = None; 214 | for t in get_process(): 215 | if t.GetStopReason() != lldb.eStopReasonNone and t.GetStopReason() != lldb.eStopReasonInvalid: 216 | ret = t.GetFrameAtIndex(0); 217 | 218 | return ret; 219 | 220 | def get_process(): 221 | return lldb.debugger.GetSelectedTarget().process; #GetTargetAtIndex(0).process; 222 | 223 | def evaluate(command): 224 | value = get_frame().EvaluateExpression(command); 225 | if value.IsValid() == False: 226 | return None; 227 | try: 228 | value = long(value.GetValue(), 10); 229 | return value; 230 | except: 231 | return None; 232 | 233 | def is_i386(): 234 | arch = get_arch(); 235 | if arch[0:1] == "i": 236 | return True; 237 | return False; 238 | 239 | def is_x64(): 240 | arch = get_arch(); 241 | if arch.startswith("x86_64") == True: 242 | return True; 243 | return False; 244 | 245 | def is_arm(): 246 | arch = get_arch(); 247 | if "arm" in arch: 248 | return True; 249 | return False; 250 | 251 | def get_pointer_size(): 252 | poisz = evaluate("sizeof(long)"); 253 | return poisz; 254 | 255 | def color_reset(): 256 | output("\033[0m"); 257 | def color_bold(): 258 | output("\033[1m"); 259 | def color_underline(): 260 | output("\033[4m"); 261 | 262 | def color(x): 263 | out_col = ""; 264 | if x == BLACK: 265 | out_col = "\033[30m"; 266 | elif x == RED: 267 | out_col = "\033[31m"; 268 | elif x == GREEN: 269 | out_col = "\033[32m"; 270 | elif x == YELLOW: 271 | out_col = "\033[33m"; 272 | elif x == BLUE: 273 | out_col = "\033[34m"; 274 | elif x == MAGENTA: 275 | out_col = "\033[35m"; 276 | elif x == CYAN: 277 | out_col = "\033[36m"; 278 | elif x == WHITE: 279 | out_col = "\033[37m"; 280 | output(out_col); 281 | 282 | def output(x): 283 | global GlobalListOutput; 284 | GlobalListOutput.append(x); 285 | 286 | def get_register(reg_name): 287 | regs = get_GPRs(); 288 | if regs == None: 289 | return "0"; 290 | for reg in regs: 291 | if reg_name == reg.GetName(): 292 | return reg.GetValue(); 293 | return "0"; #0; 294 | 295 | def get_registers(kind): 296 | """Returns the registers given the frame and the kind of registers desired. 297 | 298 | Returns None if there's no such kind. 299 | """ 300 | registerSet = get_frame().GetRegisters() # Return type of SBValueList. 301 | for value in registerSet: 302 | if kind.lower() in value.GetName().lower(): 303 | return value 304 | 305 | return None 306 | 307 | def dump_eflags(eflags): 308 | if (eflags >> 0xB) & 1: 309 | output("O "); 310 | else: 311 | output("o "); 312 | 313 | if (eflags >> 0xA) & 1: 314 | output("D "); 315 | else: 316 | output("d "); 317 | 318 | if (eflags >> 9) & 1: 319 | output("I "); 320 | else: 321 | output("i "); 322 | 323 | if (eflags >> 8) & 1: 324 | output("T "); 325 | else: 326 | output("t "); 327 | 328 | if (eflags >> 7) & 1: 329 | output("S "); 330 | else: 331 | output("s "); 332 | 333 | if (eflags >> 6) & 1: 334 | output("Z "); 335 | else: 336 | output("z "); 337 | 338 | if (eflags >> 4) & 1: 339 | output("A "); 340 | else: 341 | output("a "); 342 | 343 | if (eflags >> 2) & 1: 344 | output("P "); 345 | else: 346 | output("p "); 347 | 348 | if eflags & 1: 349 | output("C"); 350 | else: 351 | output("c"); 352 | 353 | def reg64(): 354 | global old_cs; 355 | global old_ds; 356 | global old_fs; 357 | global old_gs; 358 | global old_ss; 359 | global old_es; 360 | global old_rax; 361 | global old_rcx; 362 | global old_rdx; 363 | global old_rbx; 364 | global old_rsp; 365 | global old_rbp; 366 | global old_rsi; 367 | global old_rdi; 368 | global old_r8; 369 | global old_r9; 370 | global old_r10; 371 | global old_r11; 372 | global old_r12; 373 | global old_r13; 374 | global old_r14; 375 | global old_r15; 376 | global old_rflags; 377 | global old_rip; 378 | 379 | rax = int(str(get_register("rax")).strip().split()[0], 16); 380 | rcx = int(str(get_register("rcx")).strip().split()[0], 16); 381 | rdx = int(str(get_register("rdx")).strip().split()[0], 16); 382 | rbx = int(str(get_register("rbx")).strip().split()[0], 16); 383 | rsp = int(str(get_register("rsp")).strip().split()[0], 16); 384 | rbp = int(str(get_register("rbp")).strip().split()[0], 16); 385 | rsi = int(str(get_register("rsi")).strip().split()[0], 16); 386 | rdi = int(str(get_register("rdi")).strip().split()[0], 16); 387 | r8 = int(str(get_register("r8")).strip().split()[0], 16); 388 | r9 = int(str(get_register("r9")).strip().split()[0], 16); 389 | r10 = int(str(get_register("r10")).strip().split()[0], 16); 390 | r11 = int(str(get_register("r11")).strip().split()[0], 16); 391 | r12 = int(str(get_register("r12")).strip().split()[0], 16); 392 | r13 = int(str(get_register("r13")).strip().split()[0], 16); 393 | r14 = int(str(get_register("r14")).strip().split()[0], 16); 394 | r15 = int(str(get_register("r15")).strip().split()[0], 16); 395 | rip = int(str(get_register("rip")).strip().split()[0], 16); 396 | rflags = int(str(get_register("rflags")).strip().split()[0], 16); 397 | cs = int(str(get_register("cs")).strip().split()[0], 16); 398 | gs = int(str(get_register("gs")).strip().split()[0], 16); 399 | fs = int(str(get_register("fs")).strip().split()[0], 16); 400 | 401 | # not needed as x64 doesn't use them... 402 | # ds = int(str(get_register("ds")).strip().split()[0], 16); 403 | # ss = int(str(get_register("ss")).strip().split()[0], 16); 404 | 405 | color(COLOR_REGNAME); 406 | output(" RAX: "); 407 | if rax == old_rax: 408 | color(COLOR_REGVAL); 409 | else: 410 | color(COLOR_REGVAL_MODIFIED); 411 | output("0x%.016lX" % (rax)); 412 | old_rax = rax; 413 | 414 | color(COLOR_REGNAME); 415 | output(" RBX: ") 416 | if rbx == old_rbx: 417 | color(COLOR_REGVAL); 418 | else: 419 | color(COLOR_REGVAL_MODIFIED); 420 | output("0x%.016lX" % (rbx)); 421 | old_rbx = rbx; 422 | 423 | color(COLOR_REGNAME); 424 | output(" RBP: "); 425 | if rbp == old_rbp: 426 | color(COLOR_REGVAL); 427 | else: 428 | color(COLOR_REGVAL_MODIFIED); 429 | output("0x%.016lX" % (rbp)); 430 | old_rbp = rbp; 431 | 432 | color(COLOR_REGNAME); 433 | output(" RSP: "); 434 | if rsp == old_rsp: 435 | color(COLOR_REGVAL); 436 | else: 437 | color(COLOR_REGVAL_MODIFIED); 438 | output("0x%.016lX" % (rsp)); 439 | old_rsp = rsp; 440 | 441 | output(" "); 442 | color_bold(); 443 | color_underline(); 444 | color(COLOR_CPUFLAGS); 445 | dump_eflags(rflags); 446 | color_reset(); 447 | 448 | output("\n"); 449 | 450 | 451 | color(COLOR_REGNAME); 452 | output(" RDI: "); 453 | if rdi == old_rdi: 454 | color(COLOR_REGVAL); 455 | else: 456 | color(COLOR_REGVAL_MODIFIED); 457 | output("0x%.016lX" % (rdi)); 458 | old_rdi = rdi; 459 | 460 | color(COLOR_REGNAME); 461 | output(" RSI: "); 462 | if rsi == old_rsi: 463 | color(COLOR_REGVAL); 464 | else: 465 | color(COLOR_REGVAL_MODIFIED); 466 | output("0x%.016lX" % (rsi)); 467 | old_rsi = rsi; 468 | 469 | color(COLOR_REGNAME); 470 | output(" RDX: "); 471 | if rdx == old_rdx: 472 | color(COLOR_REGVAL); 473 | else: 474 | color(COLOR_REGVAL_MODIFIED); 475 | output("0x%.016lX" % (rdx)); 476 | old_rdx = rdx; 477 | 478 | color(COLOR_REGNAME); 479 | output(" RCX: "); 480 | if rcx == old_rcx: 481 | color(COLOR_REGVAL); 482 | else: 483 | color(COLOR_REGVAL_MODIFIED); 484 | output("0x%.016lX" % (rcx)); 485 | old_rcx = rcx; 486 | 487 | color(COLOR_REGNAME); 488 | output(" RIP: "); 489 | if rip == old_rip: 490 | color(COLOR_REGVAL); 491 | else: 492 | color(COLOR_REGVAL_MODIFIED); 493 | output("0x%.016lX" % (rip)); 494 | old_rip = rip; 495 | output("\n"); 496 | 497 | color(COLOR_REGNAME); 498 | output(" R8: "); 499 | if r8 == old_r8: 500 | color(COLOR_REGVAL); 501 | else: 502 | color(COLOR_REGVAL_MODIFIED); 503 | output("0x%.016lX" % (r8)); 504 | old_r8 = r8; 505 | 506 | color(COLOR_REGNAME); 507 | output(" R9: "); 508 | if r9 == old_r9: 509 | color(COLOR_REGVAL); 510 | else: 511 | color(COLOR_REGVAL_MODIFIED); 512 | output("0x%.016lX" % (r9)); 513 | old_r9 = r9; 514 | 515 | color(COLOR_REGNAME); 516 | output(" R10: "); 517 | if r10 == old_r10: 518 | color(COLOR_REGVAL); 519 | else: 520 | color(COLOR_REGVAL_MODIFIED); 521 | output("0x%.016lX" % (r10)); 522 | old_r10 = r10; 523 | 524 | color(COLOR_REGNAME); 525 | output(" R11: "); 526 | if r11 == old_r11: 527 | color(COLOR_REGVAL); 528 | else: 529 | color(COLOR_REGVAL_MODIFIED); 530 | output("0x%.016lX" % (r11)); 531 | old_r11 = r11; 532 | 533 | color(COLOR_REGNAME); 534 | output(" R12: "); 535 | if r12 == old_r12: 536 | color(COLOR_REGVAL); 537 | else: 538 | color(COLOR_REGVAL_MODIFIED); 539 | output("0x%.016lX" % (r12)); 540 | old_r12 = r12; 541 | 542 | output("\n"); 543 | 544 | color(COLOR_REGNAME); 545 | output(" R13: "); 546 | if r13 == old_r13: 547 | color(COLOR_REGVAL); 548 | else: 549 | color(COLOR_REGVAL_MODIFIED); 550 | output("0x%.016lX" % (r13)); 551 | old_r13 = r13; 552 | 553 | color(COLOR_REGNAME); 554 | output(" R14: "); 555 | if r14 == old_r14: 556 | color(COLOR_REGVAL); 557 | else: 558 | color(COLOR_REGVAL_MODIFIED); 559 | output("0x%.016lX" % (r14)); 560 | old_r14 = r14; 561 | 562 | color(COLOR_REGNAME); 563 | output(" R15: "); 564 | if r15 == old_r15: 565 | color(COLOR_REGVAL); 566 | else: 567 | color(COLOR_REGVAL_MODIFIED); 568 | output("0x%.016lX" % (r15)); 569 | old_r15 = r15; 570 | output("\n"); 571 | 572 | color(COLOR_REGNAME); 573 | output(" CS: "); 574 | if cs == old_cs: 575 | color(COLOR_REGVAL); 576 | else: 577 | color(COLOR_REGVAL_MODIFIED); 578 | output("%.04X" % (cs)); 579 | old_cs = cs; 580 | 581 | color(COLOR_REGNAME); 582 | output(" FS: "); 583 | if fs == old_fs: 584 | color(COLOR_REGVAL); 585 | else: 586 | color(COLOR_REGVAL_MODIFIED); 587 | output("%.04X" % (fs)); 588 | old_fs = fs; 589 | 590 | color(COLOR_REGNAME); 591 | output(" GS: "); 592 | if gs == old_gs: 593 | color(COLOR_REGVAL); 594 | else: 595 | color(COLOR_REGVAL_MODIFIED); 596 | output("%.04X" % (gs)); 597 | old_gs = gs; 598 | output("\n"); 599 | 600 | def reg32(): 601 | global old_eax; 602 | global old_ecx; 603 | global old_edx; 604 | global old_ebx; 605 | global old_esp; 606 | global old_ebp; 607 | global old_esi; 608 | global old_edi; 609 | global old_eflags; 610 | global old_cs; 611 | global old_ds; 612 | global old_fs; 613 | global old_gs; 614 | global old_ss; 615 | global old_es; 616 | global old_eip; 617 | 618 | color(COLOR_REGNAME); 619 | output(" EAX: "); 620 | eax = int(get_register("eax"), 16); 621 | if eax == old_eax: 622 | color(COLOR_REGVAL); 623 | else: 624 | color(COLOR_REGVAL_MODIFIED); 625 | output("0x%.08X" % (eax)); 626 | old_eax = eax; 627 | 628 | color(COLOR_REGNAME); 629 | output(" EBX: "); 630 | ebx = int(get_register("ebx"), 16); 631 | if ebx == old_ebx: 632 | color(COLOR_REGVAL); 633 | else: 634 | color(COLOR_REGVAL_MODIFIED); 635 | output("0x%.08X" % (ebx)); 636 | old_ebx = ebx; 637 | 638 | color(COLOR_REGNAME); 639 | output(" ECX: "); 640 | ecx = int(get_register("ecx"), 16); 641 | if ecx == old_ecx: 642 | color(COLOR_REGVAL); 643 | else: 644 | color(COLOR_REGVAL_MODIFIED); 645 | output("0x%.08X" % (ecx)); 646 | old_ecx = ecx; 647 | 648 | color(COLOR_REGNAME); 649 | output(" EDX: "); 650 | edx = int(get_register("edx"), 16); 651 | if edx == old_edx: 652 | color(COLOR_REGVAL); 653 | else: 654 | color(COLOR_REGVAL_MODIFIED); 655 | output("0x%.08X" % (edx)); 656 | old_edx = edx; 657 | 658 | output(" "); 659 | eflags = int(get_register("eflags"), 16); 660 | color_bold(); 661 | color_underline(); 662 | color(COLOR_CPUFLAGS); 663 | dump_eflags(eflags); 664 | color_reset(); 665 | 666 | output("\n"); 667 | 668 | color(COLOR_REGNAME); 669 | output(" ESI: "); 670 | esi = int(get_register("esi"), 16); 671 | if esi == old_esi: 672 | color(COLOR_REGVAL); 673 | else: 674 | color(COLOR_REGVAL_MODIFIED); 675 | output("0x%.08X" % (esi)); 676 | old_esi = esi; 677 | 678 | color(COLOR_REGNAME); 679 | output(" EDI: "); 680 | edi = int(get_register("edi"), 16); 681 | if edi == old_edi: 682 | color(COLOR_REGVAL); 683 | else: 684 | color(COLOR_REGVAL_MODIFIED); 685 | output("0x%.08X" % (edi)); 686 | old_edi = edi; 687 | 688 | color(COLOR_REGNAME); 689 | output(" EBP: "); 690 | ebp = int(get_register("ebp"), 16); 691 | if ebp == old_ebp: 692 | color(COLOR_REGVAL); 693 | else: 694 | color(COLOR_REGVAL_MODIFIED); 695 | output("0x%.08X" % (ebp)); 696 | old_ebp = ebp; 697 | 698 | color(COLOR_REGNAME); 699 | output(" ESP: "); 700 | esp = int(get_register("esp"), 16); 701 | if esp == old_esp: 702 | color(COLOR_REGVAL); 703 | else: 704 | color(COLOR_REGVAL_MODIFIED); 705 | output("0x%.08X" % (esp)); 706 | old_esp = esp; 707 | 708 | color(COLOR_REGNAME); 709 | output(" EIP: "); 710 | eip = int(get_register("eip"), 16); 711 | if eip == old_eip: 712 | color(COLOR_REGVAL); 713 | else: 714 | color(COLOR_REGVAL_MODIFIED); 715 | output("0x%.08X" % (eip)); 716 | old_eip = eip; 717 | output("\n"); 718 | 719 | color(COLOR_REGNAME); 720 | output(" CS: "); 721 | cs = int(get_register("cs"), 16); 722 | if cs == old_cs: 723 | color(COLOR_REGVAL); 724 | else: 725 | color(COLOR_REGVAL_MODIFIED); 726 | output("%.04X" % (cs)); 727 | old_cs = cs; 728 | 729 | color(COLOR_REGNAME); 730 | output(" DS: "); 731 | ds = int(get_register("ds"), 16); 732 | if ds == old_ds: 733 | color(COLOR_REGVAL); 734 | else: 735 | color(COLOR_REGVAL_MODIFIED); 736 | output("%.04X" % (ds)); 737 | old_ds = ds; 738 | 739 | color(COLOR_REGNAME); 740 | output(" ES: "); 741 | es = int(get_register("es"), 16); 742 | if es == old_es: 743 | color(COLOR_REGVAL); 744 | else: 745 | color(COLOR_REGVAL_MODIFIED); 746 | output("%.04X" % (es)); 747 | old_es = es; 748 | 749 | color(COLOR_REGNAME); 750 | output(" FS: "); 751 | fs = int(get_register("fs"), 16); 752 | if fs == old_fs: 753 | color(COLOR_REGVAL); 754 | else: 755 | color(COLOR_REGVAL_MODIFIED); 756 | output("%.04X" % (fs)); 757 | old_fs = fs; 758 | 759 | color(COLOR_REGNAME); 760 | output(" GS: "); 761 | gs = int(get_register("gs"), 16); 762 | if gs == old_gs: 763 | color(COLOR_REGVAL); 764 | else: 765 | color(COLOR_REGVAL_MODIFIED); 766 | output("%.04X" % (gs)); 767 | old_gs = gs; 768 | 769 | color(COLOR_REGNAME); 770 | output(" SS: "); 771 | ss = int(get_register("ss"), 16); 772 | if ss == old_ss: 773 | color(COLOR_REGVAL); 774 | else: 775 | color(COLOR_REGVAL_MODIFIED); 776 | output("%.04X" % (ss)); 777 | old_ss = ss; 778 | output("\n"); 779 | 780 | def dump_cpsr(cpsr): 781 | if (cpsr >> 31) & 1: 782 | output("N "); 783 | else: 784 | output("n "); 785 | 786 | if (cpsr >> 30) & 1: 787 | output("Z "); 788 | else: 789 | output("z "); 790 | 791 | if (cpsr >> 29) & 1: 792 | output("C "); 793 | else: 794 | output("c "); 795 | 796 | if (cpsr >> 28) & 1: 797 | output("V "); 798 | else: 799 | output("v "); 800 | 801 | if (cpsr >> 27) & 1: 802 | output("Q "); 803 | else: 804 | output("q "); 805 | 806 | if (cpsr >> 24) & 1: 807 | output("J "); 808 | else: 809 | output("j "); 810 | 811 | if (cpsr >> 9) & 1: 812 | output("E "); 813 | else: 814 | output("e "); 815 | if (cpsr >> 8) & 1: 816 | output("A "); 817 | else: 818 | output("a "); 819 | if (cpsr >> 7) & 1: 820 | output("I "); 821 | else: 822 | output("i "); 823 | if (cpsr >> 6) & 1: 824 | output("F "); 825 | else: 826 | output("f "); 827 | if (cpsr >> 5) & 1: 828 | output("T"); 829 | else: 830 | output("t"); 831 | 832 | def regarm(): 833 | global old_arm_r0; 834 | global old_arm_r1; 835 | global old_arm_r2; 836 | global old_arm_r3; 837 | global old_arm_r4; 838 | global old_arm_r5; 839 | global old_arm_r6; 840 | global old_arm_r7; 841 | global old_arm_r8; 842 | global old_arm_r9; 843 | global old_arm_r10; 844 | global old_arm_r11; 845 | global old_arm_r12; 846 | global old_arm_sp; 847 | global old_arm_lr; 848 | global old_arm_pc; 849 | global old_arm_cpsr; 850 | 851 | color(COLOR_REGNAME); 852 | output(" R0: "); 853 | r0 = int(get_register("r0"), 16); 854 | if r0 == old_arm_r0: 855 | color(COLOR_REGVAL); 856 | else: 857 | color(COLOR_REGVAL_MODIFIED); 858 | output("0x%.08X" % (r0)); 859 | old_arm_r0 = r0; 860 | 861 | color(COLOR_REGNAME); 862 | output(" R1: "); 863 | r1 = int(get_register("r1"), 16); 864 | if r1 == old_arm_r1: 865 | color(COLOR_REGVAL); 866 | else: 867 | color(COLOR_REGVAL_MODIFIED); 868 | output("0x%.08X" % (r1)); 869 | old_arm_r1 = r1; 870 | 871 | color(COLOR_REGNAME); 872 | output(" R2: "); 873 | r2 = int(get_register("r2"), 16); 874 | if r2 == old_arm_r2: 875 | color(COLOR_REGVAL); 876 | else: 877 | color(COLOR_REGVAL_MODIFIED); 878 | output("0x%.08X" % (r2)); 879 | old_arm_r2 = r2; 880 | 881 | color(COLOR_REGNAME); 882 | output(" R3: "); 883 | r3 = int(get_register("r3"), 16); 884 | if r3 == old_arm_r3: 885 | color(COLOR_REGVAL); 886 | else: 887 | color(COLOR_REGVAL_MODIFIED); 888 | output("0x%.08X" % (r3)); 889 | old_arm_r3 = r3; 890 | 891 | output(" "); 892 | color_bold(); 893 | color_underline(); 894 | color(COLOR_CPUFLAGS); 895 | cpsr = int(get_register("cpsr"), 16); 896 | dump_cpsr(cpsr); 897 | color_reset(); 898 | 899 | output("\n"); 900 | 901 | 902 | color(COLOR_REGNAME); 903 | output(" R4: "); 904 | r4 = int(get_register("r4"), 16); 905 | if r4 == old_arm_r4: 906 | color(COLOR_REGVAL); 907 | else: 908 | color(COLOR_REGVAL_MODIFIED); 909 | output("0x%.08X" % (r4)); 910 | old_arm_r4 = r4; 911 | 912 | color(COLOR_REGNAME); 913 | output(" R5: "); 914 | r5 = int(get_register("r5"), 16); 915 | if r5 == old_arm_r5: 916 | color(COLOR_REGVAL); 917 | else: 918 | color(COLOR_REGVAL_MODIFIED); 919 | output("0x%.08X" % (r5)); 920 | old_arm_r5 = r5; 921 | 922 | color(COLOR_REGNAME); 923 | output(" R6: "); 924 | r6 = int(get_register("r6"), 16); 925 | if r6 == old_arm_r6: 926 | color(COLOR_REGVAL); 927 | else: 928 | color(COLOR_REGVAL_MODIFIED); 929 | output("0x%.08X" % (r6)); 930 | old_arm_r6 = r6; 931 | 932 | color(COLOR_REGNAME); 933 | output(" R7: "); 934 | r7 = int(get_register("r7"), 16); 935 | if r7 == old_arm_r7: 936 | color(COLOR_REGVAL); 937 | else: 938 | color(COLOR_REGVAL_MODIFIED); 939 | output("0x%.08X" % (r7)); 940 | old_arm_r7 = r7; 941 | 942 | output("\n"); 943 | 944 | color(COLOR_REGNAME); 945 | output(" R8: "); 946 | r8 = int(get_register("r8"), 16); 947 | if r8 == old_arm_r8: 948 | color(COLOR_REGVAL); 949 | else: 950 | color(COLOR_REGVAL_MODIFIED); 951 | output("0x%.08X" % (r8)); 952 | old_arm_r8 = r8; 953 | 954 | color(COLOR_REGNAME); 955 | output(" R9: "); 956 | r9 = int(get_register("r9"), 16); 957 | if r9 == old_arm_r9: 958 | color(COLOR_REGVAL); 959 | else: 960 | color(COLOR_REGVAL_MODIFIED); 961 | output("0x%.08X" % (r9)); 962 | old_arm_r9 = r9; 963 | 964 | color(COLOR_REGNAME); 965 | output(" R10: "); 966 | r10 = int(get_register("r10"), 16); 967 | if r10 == old_arm_r10: 968 | color(COLOR_REGVAL); 969 | else: 970 | color(COLOR_REGVAL_MODIFIED); 971 | output("0x%.08X" % (r10)); 972 | old_arm_r10 = r10; 973 | 974 | color(COLOR_REGNAME); 975 | output(" R11: "); 976 | r11 = int(get_register("r11"), 16); 977 | if r11 == old_arm_r11: 978 | color(COLOR_REGVAL); 979 | else: 980 | color(COLOR_REGVAL_MODIFIED); 981 | output("0x%.08X" % (r11)); 982 | old_arm_r11 = r11; 983 | 984 | output("\n"); 985 | 986 | color(COLOR_REGNAME); 987 | output(" R12: "); 988 | r12 = int(get_register("r12"), 16); 989 | if r12 == old_arm_r12: 990 | color(COLOR_REGVAL); 991 | else: 992 | color(COLOR_REGVAL_MODIFIED); 993 | output("0x%.08X" % (r12)); 994 | old_arm_r12 = r12; 995 | 996 | color(COLOR_REGNAME); 997 | output(" SP: "); 998 | sp = int(get_register("sp"), 16); 999 | if sp == old_arm_sp: 1000 | color(COLOR_REGVAL); 1001 | else: 1002 | color(COLOR_REGVAL_MODIFIED); 1003 | output("0x%.08X" % (sp)); 1004 | old_arm_sp = sp; 1005 | 1006 | color(COLOR_REGNAME); 1007 | output(" LR: "); 1008 | lr = int(get_register("lr"), 16); 1009 | if lr == old_arm_lr: 1010 | color(COLOR_REGVAL); 1011 | else: 1012 | color(COLOR_REGVAL_MODIFIED); 1013 | output("0x%.08X" % (lr)); 1014 | old_arm_lr = lr; 1015 | 1016 | color(COLOR_REGNAME); 1017 | output(" PC: "); 1018 | pc = int(get_register("pc"), 16); 1019 | if pc == old_arm_pc: 1020 | color(COLOR_REGVAL); 1021 | else: 1022 | color(COLOR_REGVAL_MODIFIED); 1023 | output("0x%.08X" % (pc)); 1024 | old_arm_pc = pc; 1025 | output("\n"); 1026 | 1027 | def print_registers(): 1028 | arch = get_arch(); 1029 | if is_i386(): 1030 | reg32(); 1031 | elif is_x64(): 1032 | reg64(); 1033 | elif is_arm(): 1034 | regarm(); 1035 | def get_GPRs(): 1036 | """Returns the general purpose registers of the frame as an SBValue. 1037 | 1038 | The returned SBValue object is iterable. An example: 1039 | ... 1040 | from lldbutil import get_GPRs 1041 | regs = get_GPRs(frame) 1042 | for reg in regs: 1043 | print "%s => %s" % (reg.GetName(), reg.GetValue()) 1044 | ... 1045 | """ 1046 | return get_registers("general purpose") 1047 | 1048 | def HandleHookStopOnTarget(debugger, command, result, dict): 1049 | # Don't display anything if we're inside Xcode 1050 | if os.getenv('PATH').startswith('/Applications/Xcode.app'): 1051 | return 1052 | 1053 | global GlobalListOutput; 1054 | global arm_type; 1055 | 1056 | debugger.SetAsync(True); 1057 | frame = get_frame(); 1058 | if not frame: return; 1059 | 1060 | thread= frame.GetThread(); 1061 | while True: 1062 | frame = get_frame(); 1063 | thread = frame.GetThread(); 1064 | #print("----------------------------------"); 1065 | #for t in get_process(): 1066 | # print("Thread stop reason : %d" % (t.GetStopReason())); 1067 | 1068 | if thread.GetStopReason() == lldb.eStopReasonNone or thread.GetStopReason() == lldb.eStopReasonInvalid: 1069 | time.sleep(0.001); 1070 | else: 1071 | break; 1072 | 1073 | GlobalListOutput = []; 1074 | 1075 | arch = get_arch(); 1076 | if not is_i386() and not is_x64() and not is_arm(): 1077 | #this is for ARM probably in the future... when I will need it... 1078 | print("Unknown architecture : " + arch); 1079 | return; 1080 | 1081 | output("\n"); 1082 | color(COLOR_SEPARATOR); 1083 | if is_i386() or is_arm(): 1084 | output("---------------------------------------------------------------------------------"); 1085 | elif is_x64(): 1086 | output("-----------------------------------------------------------------------------------------------------------------------"); 1087 | 1088 | color_bold(); 1089 | output("[regs]\n"); 1090 | color_reset(); 1091 | print_registers(); 1092 | 1093 | color(COLOR_SEPARATOR); 1094 | if is_i386() or is_arm(): 1095 | output("---------------------------------------------------------------------------------"); 1096 | elif is_x64(): 1097 | output("-----------------------------------------------------------------------------------------------------------------------"); 1098 | color_bold(); 1099 | output("[code]\n"); 1100 | color_reset(); 1101 | 1102 | if is_i386(): 1103 | pc = get_register("eip"); 1104 | elif is_x64(): 1105 | pc = get_register("rip"); 1106 | elif is_arm(): 1107 | pc = get_register("pc"); 1108 | 1109 | res = lldb.SBCommandReturnObject(); 1110 | if is_arm(): 1111 | cpsr = int(get_register("cpsr"), 16); 1112 | t = (cpsr >> 5) & 1; 1113 | if t: 1114 | #it's thumb 1115 | arm_type = "thumbv7-apple-ios"; 1116 | else: 1117 | arm_type = "armv7-apple-ios"; 1118 | lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble -A " + arm_type + " --start-address=" + pc + " --count=8", res) 1119 | else: 1120 | lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble --start-address=" + pc + " --count=8", res); 1121 | data = res.GetOutput(); 1122 | #split lines... and mark currently executed code... 1123 | data = data.split("\n"); 1124 | #detemine what to hl, as sometimes lldb won't put => into stoped thread... well... 1125 | #need to check if first sym is => or ' ' which means this is name without symol 1126 | #symbols are stored 1st so here we go... 1127 | line_to_hl = 0; 1128 | #if data[0][0:2] == "->": 1129 | # line_to_hl = 0; 1130 | #if data[0][0:2] != ' ': 1131 | # line_to_hl = 1; 1132 | 1133 | #now we look when pc is held in disassembly and we color only that line 1134 | pc_text = int(str(pc).strip().split()[0], 16); 1135 | pc_text = hex(pc_text); 1136 | #print(pc_text); 1137 | for idx,x in enumerate(data): 1138 | if pc_text in x: 1139 | line_to_hl = idx; 1140 | break; 1141 | for idx,x in enumerate(data): 1142 | if line_to_hl == idx: #x[0:2] == "->" and idx < 3: 1143 | color(COLOR_HIGHLIGHT_LINE); 1144 | color_bold(); 1145 | output(x); 1146 | color_reset(); 1147 | else: 1148 | output(x); 1149 | output("\n"); 1150 | #output(res.GetOutput()); 1151 | color(COLOR_SEPARATOR); 1152 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1153 | output("---------------------------------------------------------------------------------------"); 1154 | elif get_pointer_size() == 8: #is_x64(): 1155 | output("-----------------------------------------------------------------------------------------------------------------------------"); 1156 | color_reset(); 1157 | output("\n"); 1158 | 1159 | output("Stop reason : " + str(thread.GetStopDescription(100))); #str(lldb.debugger.GetSelectedTarget().process.selected_thread.GetStopDescription(100))); 1160 | output("\r"); 1161 | data = "".join(GlobalListOutput); 1162 | 1163 | result.PutCString(data); 1164 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1165 | return 0; 1166 | 1167 | def LoadBreakPointsRva(debugger, command, result, dict): 1168 | global GlobalOutputList; 1169 | GlobalOutputList = []; 1170 | ''' 1171 | frame = get_frame(); 1172 | target = lldb.debugger.GetSelectedTarget(); 1173 | 1174 | nummods = target.GetNumModules(); 1175 | #for x in range (0, nummods): 1176 | # mod = target.GetModuleAtIndex(x); 1177 | # #print(dir(mod)); 1178 | # print(target.GetModuleAtIndex(x)); 1179 | # for sec in mod.section_iter(): 1180 | # addr = sec.GetLoadAddress(target); 1181 | # name = sec.GetName(); 1182 | # print(hex(addr)); 1183 | 1184 | #1st module is executable 1185 | mod = target.GetModuleAtIndex(0); 1186 | sec = mod.GetSectionAtIndex(0); 1187 | loadaddr = sec.GetLoadAddress(target); 1188 | if loadaddr == lldb.LLDB_INVALID_ADDRESS: 1189 | sec = mod.GetSectionAtIndex(1); 1190 | loadaddr = sec.GetLoadAddress(target); 1191 | print(hex(loadaddr)); 1192 | ''' 1193 | 1194 | target = lldb.debugger.GetSelectedTarget(); 1195 | mod = target.GetModuleAtIndex(0); 1196 | sec = mod.GetSectionAtIndex(0); 1197 | loadaddr = sec.GetLoadAddress(target); 1198 | if loadaddr == lldb.LLDB_INVALID_ADDRESS: 1199 | sec = mod.GetSectionAtIndex(1); 1200 | loadaddr = sec.GetLoadAddress(target); 1201 | try: 1202 | f = open(command, "r"); 1203 | except: 1204 | output("Failed to load file : " + command); 1205 | result.PutCString("".join(GlobalListOutput)); 1206 | return; 1207 | while True: 1208 | line = f.readline(); 1209 | if not line: break; 1210 | line = line.rstrip(); 1211 | if not line: break; 1212 | debugger.HandleCommand("breakpoint set -a " + hex(loadaddr + long(line, 16))); 1213 | f.close(); 1214 | 1215 | 1216 | def LoadBreakPoints(debugger, command, result, dict): 1217 | global GlobalOutputList; 1218 | GlobalOutputList = []; 1219 | 1220 | try: 1221 | f = open(command, "r"); 1222 | except: 1223 | output("Failed to load file : " + command); 1224 | result.PutCString("".join(GlobalListOutput)); 1225 | return; 1226 | while True: 1227 | line = f.readline(); 1228 | if not line: 1229 | break; 1230 | line = line.rstrip(); 1231 | if not line: 1232 | break; 1233 | debugger.HandleCommand("breakpoint set --name " + line); 1234 | f.close(); 1235 | 1236 | ''' 1237 | si, c, r instruction override deault ones to consume their output. 1238 | For example: 1239 | si is thread step-in which by default dumps thread and frame info 1240 | after every step. Consuming output of this instruction allows us 1241 | to nicely display informations in our hook-stop 1242 | Same goes for c and r (continue and run) 1243 | ''' 1244 | def si(debugger, command, result, dict): 1245 | debugger.SetAsync(True); 1246 | res = lldb.SBCommandReturnObject(); 1247 | lldb.debugger.GetSelectedTarget().process.selected_thread.StepInstruction(False); 1248 | result.SetStatus(lldb.eReturnStatusSuccessFinishNoResult); 1249 | 1250 | def c(debugger, command, result, dict): 1251 | debugger.SetAsync(True); 1252 | res = lldb.SBCommandReturnObject(); 1253 | lldb.debugger.GetSelectedTarget().GetProcess().Continue(); 1254 | result.SetStatus(lldb.eReturnStatusSuccessFinishNoResult ); 1255 | 1256 | def r(debugger, command, result, dict): 1257 | debugger.SetAsync(True); 1258 | res = lldb.SBCommandReturnObject(); 1259 | if command[0:3] == "-c/": 1260 | index = command.find("--"); 1261 | command = command[index+2:]; 1262 | #strip -c/bin/sh or -c/bin/bash -- when arguments are passed to cmd line... 1263 | lldb.debugger.GetCommandInterpreter().HandleCommand("process launch -- " + command, res); 1264 | result.SetStatus(lldb.eReturnStatusSuccessFinishNoResult ); 1265 | 1266 | ''' 1267 | Handles 'u' command which displays instructions. Also handles output of 1268 | 'disassemble' command ... 1269 | ''' 1270 | def DumpInstructions(debugger, command, result, dict): 1271 | global GlobalListOutput; 1272 | global arm_type; 1273 | GlobalListOutput = []; 1274 | 1275 | if is_arm(): 1276 | cpsr = int(get_register("cpsr"), 16); 1277 | t = (cpsr >> 5) & 1; 1278 | if t: 1279 | #it's thumb 1280 | arm_type = "thumbv7-apple-ios"; 1281 | else: 1282 | arm_type = "armv7-apple-ios"; 1283 | res = lldb.SBCommandReturnObject(); 1284 | cmd = command.split(); 1285 | if len(cmd) == 0 or len(cmd) > 2: 1286 | if is_arm(): 1287 | lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble -A " +arm_type + " --start-address=$pc --count=8", res); 1288 | else: 1289 | lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble --start-address=$pc --count=8", res); 1290 | elif len(cmd) == 1: 1291 | if is_arm(): 1292 | lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble -A "+arm_type+" --start-address=" + cmd[0] + " --count=8", res); 1293 | else: 1294 | lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble --start-address=" + cmd[0] + " --count=8", res); 1295 | else: 1296 | if is_arm(): 1297 | lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble -A "+arm_type+" --start-address=" + cmd[0] + " --count="+cmd[1], res); 1298 | lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble --start-address=" + cmd[0] + " --count="+cmd[1], res); 1299 | 1300 | if res.Succeeded() == True: 1301 | output(res.GetOutput()); 1302 | else: 1303 | output("Error getting instructions for : " + command); 1304 | 1305 | result.PutCString("".join(GlobalListOutput)); 1306 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1307 | 1308 | ''' 1309 | Implements stepover instruction. Unfortunatelly here is no internal breakpoint exposed to Python 1310 | thus all breaks have to be visible. Internal breakpoints are breakpoints which are < 0 (eg. -1 etc...) 1311 | and their existance is visible from : 1312 | lldb/sources/Target/Target.cpp 1313 | 1314 | BreakpointSP 1315 | Target::CreateBreakpoint (const FileSpecList *containingModules, 1316 | const FileSpec &file, 1317 | uint32_t line_no, 1318 | LazyBool check_inlines, 1319 | LazyBool skip_prologue, 1320 | bool internal, 1321 | bool hardware) 1322 | 1323 | ''' 1324 | 1325 | bplist = []; 1326 | 1327 | def stepo(debugger, command, result, dict): 1328 | global GlobalListOutput; 1329 | global arm_type; 1330 | GlobalListOutput = []; 1331 | debugger.SetAsync(True); 1332 | arch = get_arch(); 1333 | 1334 | result.SetStatus(lldb.eReturnStatusSuccessFinishNoResult); 1335 | 1336 | err = lldb.SBError(); 1337 | target = lldb.debugger.GetSelectedTarget(); 1338 | 1339 | if is_arm(): 1340 | cpsr = int(get_register("cpsr"), 16); 1341 | t = (cpsr >> 5) & 1; 1342 | if t: 1343 | #it's thumb 1344 | arm_type = "thumbv7-apple-ios"; 1345 | else: 1346 | arm_type = "armv7-apple-ios"; 1347 | 1348 | res = lldb.SBCommandReturnObject(); 1349 | #if is_arm(): 1350 | # lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble -A " +arm_type + " --raw --start-address=$pc --count=2", res); 1351 | #else: 1352 | # lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble --raw --start-address=$pc --count=2", res); 1353 | 1354 | lldb.debugger.GetCommandInterpreter().HandleCommand("x/2i $pc", res); 1355 | if res.Succeeded() != True: 1356 | output("[X] Error in stepo... can't disassemble at pc"); 1357 | return; 1358 | 1359 | #use regex to locate hex addrress which is between 8-16 1360 | #as lldb changes disassembly very often... sometimes is has -> 1361 | #sometimes doesn't, and instead of always looking for different 1362 | #pattern, just use regex... Matching hex is dropped to 4 digits 1363 | #because of x32 where it prints 4 digits... 1364 | stuff = res.GetOutput(); 1365 | stuff = stuff.splitlines(True); 1366 | newlst = []; 1367 | for x in stuff: 1368 | if x == "\n": continue; 1369 | newlst.append(x); 1370 | stuff = newlst; 1371 | 1372 | p = re.compile("0x[\da-fA-F]{1,16}"); 1373 | current_pc = p.search(stuff[0]).group(0); 1374 | next_pc = p.search(stuff[1]).group(0); 1375 | current_pc = long(current_pc, 16); 1376 | next_pc = long(next_pc, 16); 1377 | 1378 | pc_inst = stuff[0].split(";")[0]; 1379 | if is_arm(): 1380 | if "blx" in pc_inst or "bl " in pc_inst: 1381 | breakpoint = target.BreakpointCreateByAddress(next_pc); 1382 | breakpoint.SetThreadID(get_frame().GetThread().GetThreadID()); 1383 | breakpoint.SetOneShot(True); 1384 | breakpoint.SetThreadID(get_frame().GetThread().GetThreadID()); 1385 | target.GetProcess().Continue(); 1386 | #debugger.HandleCommand("c"); 1387 | #debugger.HandleCommand("thread step-inst-over"); 1388 | return; 1389 | else: 1390 | lldb.debugger.GetSelectedTarget().process.selected_thread.StepInstruction(False); 1391 | #debugger.HandleCommand("si"); 1392 | return; 1393 | if "call" in pc_inst or "movs" in pc_inst or "stos" in pc_inst or "loop" in pc_inst or "cmps" in pc_inst: 1394 | breakpoint = target.BreakpointCreateByAddress(next_pc); 1395 | breakpoint.SetOneShot(True); 1396 | breakpoint.SetThreadID(get_frame().GetThread().GetThreadID()); 1397 | target.GetProcess().Continue(); 1398 | else: 1399 | lldb.debugger.GetSelectedTarget().process.selected_thread.StepInstruction(False); 1400 | 1401 | def hexdump(addr, chars, sep, width ): 1402 | l = []; 1403 | while chars: 1404 | line = chars[:width] 1405 | chars = chars[width:] 1406 | line = line.ljust( width, '\000' ) 1407 | arch = get_arch(); 1408 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1409 | szaddr = "0x%.08X" % addr; 1410 | else: # is_x64(): 1411 | szaddr = "0x%.016lX" % addr; 1412 | l.append("\033[1m%s :\033[0m %s%s \033[1m%s\033[0m" % (szaddr, sep.join( "%02X" % ord(c) for c in line ), sep, quotechars( line ))); 1413 | addr += 0x10; 1414 | return "\n".join(l); 1415 | 1416 | def quotechars( chars ): 1417 | #return ''.join( ['.', c][c.isalnum()] for c in chars ) 1418 | data = ""; 1419 | for x in chars: 1420 | if ord(x) >= 0x20 and ord(x) <= 126: 1421 | data += x; 1422 | else: 1423 | data += "."; 1424 | return data; 1425 | 1426 | ''' 1427 | Output nice hexdump... Should be db (in the future) so we can give dw/dd/dq 1428 | outputs as it's done with any normal debugger... 1429 | ''' 1430 | def dd(debugger, command, result, dict): 1431 | global GlobalListOutput; 1432 | 1433 | GlobalListOutput = []; 1434 | 1435 | arch = get_arch(); 1436 | value = get_frame().EvaluateExpression(command); 1437 | if value.IsValid() == False: 1438 | output("Error evaluating expression : " + command); 1439 | result.PutCString("".join(GlobalListOutput)); 1440 | return; 1441 | try: 1442 | value = int(value.GetValue(), 10); 1443 | except: 1444 | output("Error evaluating expression : " + command); 1445 | result.PutCString("".join(GlobalListOutput)); 1446 | return; 1447 | 1448 | err = lldb.SBError(); 1449 | target = lldb.debugger.GetSelectedTarget(); 1450 | size = 0x100; 1451 | while size != 0: 1452 | membuff = target.GetProcess().ReadMemory(value, size, err); 1453 | if err.Success() == False and size == 0: 1454 | output(str(err)); 1455 | result.PutCString("".join(GlobalListOutput)); 1456 | return; 1457 | if err.Success() == True: 1458 | break; 1459 | size = size - 1; 1460 | membuff = membuff + "\x00" * (0x100-size); 1461 | color(BLUE); 1462 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1463 | output("[0x0000:0x%.08X]" % value); 1464 | output("------------------------------------------------------"); 1465 | else: #is_x64(): 1466 | output("[0x0000:0x%.016lX]" % value); 1467 | output("------------------------------------------------------"); 1468 | color_bold(); 1469 | output("[data]") 1470 | color_reset(); 1471 | output("\n"); 1472 | #output(hexdump(value, membuff, " ", 16)); 1473 | index = 0; 1474 | while index < 0x100: 1475 | data = struct.unpack("B"*16, membuff[index:index+0x10]); 1476 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1477 | szaddr = "0x%.08X" % value; 1478 | else: #is_x64(): 1479 | szaddr = "0x%.016lX" % value; 1480 | fmtnice = "%.02X %.02X %.02X %.02X %.02X %.02X %.02X %.02X" 1481 | fmtnice = fmtnice + " - " + fmtnice; 1482 | output("\033[1m%s :\033[0m %.02X %.02X %.02X %.02X %.02X %.02X %.02X %.02X - %.02X %.02X %.02X %.02X %.02X %.02X %.02X %.02X \033[1m%s\033[0m" % 1483 | (szaddr, 1484 | data[0], 1485 | data[1], 1486 | data[2], 1487 | data[3], 1488 | data[4], 1489 | data[5], 1490 | data[6], 1491 | data[7], 1492 | data[8], 1493 | data[9], 1494 | data[10], 1495 | data[11], 1496 | data[12], 1497 | data[13], 1498 | data[14], 1499 | data[15], 1500 | quotechars(membuff[index:index+0x10]))); 1501 | if index + 0x10 != 0x100: 1502 | output("\n"); 1503 | index += 0x10; 1504 | value += 0x10; 1505 | color_reset(); 1506 | #last element of the list has all data output... 1507 | #so we remove last \n 1508 | result.PutCString("".join(GlobalListOutput)); 1509 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1510 | 1511 | def dq(debugger, command, result, dict): 1512 | global GlobalListOutput; 1513 | 1514 | GlobalListOutput = []; 1515 | 1516 | arch = get_arch(); 1517 | value = get_frame().EvaluateExpression(command); 1518 | if value.IsValid() == False: 1519 | output("Error evaluating expression : " + command); 1520 | result.PutCString("".join(GlobalListOutput)); 1521 | return; 1522 | try: 1523 | value = int(value.GetValue(), 10); 1524 | except: 1525 | output("Error evaluating expression : " + command); 1526 | result.PutCString("".join(GlobalListOutput)); 1527 | return; 1528 | 1529 | err = lldb.SBError(); 1530 | target = lldb.debugger.GetSelectedTarget(); 1531 | size = 0x100; 1532 | while size != 0: 1533 | membuff = target.GetProcess().ReadMemory(value, size, err); 1534 | if err.Success() == False and size == 0: 1535 | output(str(err)); 1536 | result.PutCString("".join(GlobalListOutput)); 1537 | return; 1538 | if err.Success() == True: 1539 | break; 1540 | size = size - 8; 1541 | membuff = membuff + "\x00" * (0x100-size); 1542 | if err.Success() == False: 1543 | output(str(err)); 1544 | result.PutCString("".join(GlobalListOutput)); 1545 | return; 1546 | 1547 | color(BLUE); 1548 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1549 | output("[0x0000:0x%.08X]" % value); 1550 | output("-------------------------------------------------------"); 1551 | else: #is_x64(): 1552 | output("[0x0000:0x%.016lX]" % value); 1553 | output("-------------------------------------------------------"); 1554 | color_bold(); 1555 | output("[data]") 1556 | color_reset(); 1557 | output("\n"); 1558 | index = 0; 1559 | while index < 0x100: 1560 | (mem0, mem1, mem2, mem3) = struct.unpack("QQQQ", membuff[index:index+0x20]); 1561 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1562 | szaddr = "0x%.08X" % value; 1563 | else: #is_x64(): 1564 | szaddr = "0x%.016lX" % value; 1565 | output("\033[1m%s :\033[0m %.016lX %.016lX %.016lX %.016lX" % (szaddr, mem0, mem1, mem2, mem3)); 1566 | if index + 0x20 != 0x100: 1567 | output("\n"); 1568 | index += 0x20; 1569 | value += 0x20; 1570 | color_reset(); 1571 | result.PutCString("".join(GlobalListOutput)); 1572 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1573 | 1574 | def ddword(debugger, command, result, dict): 1575 | global GlobalListOutput; 1576 | 1577 | GlobalListOutput = []; 1578 | 1579 | arch = get_arch(); 1580 | value = get_frame().EvaluateExpression(command); 1581 | if value.IsValid() == False: 1582 | output("Error evaluating expression : " + command); 1583 | result.PutCString("".join(GlobalListOutput)); 1584 | return; 1585 | try: 1586 | value = int(value.GetValue(), 10); 1587 | except: 1588 | output("Error evaluating expression : " + command); 1589 | result.PutCString("".join(GlobalListOutput)); 1590 | return; 1591 | 1592 | err = lldb.SBError(); 1593 | target = lldb.debugger.GetSelectedTarget(); 1594 | size = 0x100; 1595 | while size != 0: 1596 | membuff = target.GetProcess().ReadMemory(value, size, err); 1597 | if err.Success() == False and size == 0: 1598 | output(str(err)); 1599 | result.PutCString("".join(GlobalListOutput)); 1600 | return; 1601 | if err.Success() == True: 1602 | break; 1603 | size = size - 4; 1604 | membuff = membuff + "\x00" * (0x100-size); 1605 | color(BLUE); 1606 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1607 | output("[0x0000:0x%.08X]" % value); 1608 | output("----------------------------------------"); 1609 | else: #is_x64(): 1610 | output("[0x0000:0x%.016lX]" % value); 1611 | output("----------------------------------------"); 1612 | color_bold(); 1613 | output("[data]") 1614 | color_reset(); 1615 | output("\n"); 1616 | index = 0; 1617 | while index < 0x100: 1618 | (mem0, mem1, mem2, mem3) = struct.unpack("IIII", membuff[index:index+0x10]); 1619 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1620 | szaddr = "0x%.08X" % value; 1621 | else: #is_x64(): 1622 | szaddr = "0x%.016lX" % value; 1623 | output("\033[1m%s :\033[0m %.08X %.08X %.08X %.08X \033[1m%s\033[0m" % (szaddr, 1624 | mem0, 1625 | mem1, 1626 | mem2, 1627 | mem3, 1628 | quotechars(membuff[index:index+0x10]))); 1629 | if index + 0x10 != 0x100: 1630 | output("\n"); 1631 | index += 0x10; 1632 | value += 0x10; 1633 | color_reset(); 1634 | result.PutCString("".join(GlobalListOutput)); 1635 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1636 | 1637 | def dw(debugger, command, result, dict): 1638 | global GlobalListOutput; 1639 | 1640 | GlobalListOutput = []; 1641 | 1642 | arch = get_arch(); 1643 | value = get_frame().EvaluateExpression(command); 1644 | if value.IsValid() == False: 1645 | output("Error evaluating expression : " + command); 1646 | result.PutCString("".join(GlobalListOutput)); 1647 | return; 1648 | try: 1649 | value = int(value.GetValue(), 10); 1650 | except: 1651 | output("Error evaluating expression : " + command); 1652 | result.PutCString("".join(GlobalListOutput)); 1653 | return; 1654 | 1655 | err = lldb.SBError(); 1656 | target = lldb.debugger.GetSelectedTarget(); 1657 | size = 0x100; 1658 | while size != 0: 1659 | membuff = target.GetProcess().ReadMemory(value, size, err); 1660 | if err.Success() == False and size == 0: 1661 | output(str(err)); 1662 | result.PutCString("".join(GlobalListOutput)); 1663 | return; 1664 | if err.Success() == True: 1665 | break; 1666 | size = size - 2; 1667 | membuff = membuff + "\x00" * (0x100-size); 1668 | 1669 | color(BLUE); 1670 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1671 | output("[0x0000:0x%.08X]" % value); 1672 | output("--------------------------------------------"); 1673 | else: #is_x64(): 1674 | output("[0x0000:0x%.016lX]" % value); 1675 | output("--------------------------------------------"); 1676 | color_bold(); 1677 | output("[data]") 1678 | color_reset(); 1679 | output("\n"); 1680 | index = 0; 1681 | while index < 0x100: 1682 | data = struct.unpack("HHHHHHHH", membuff[index:index+0x10]); 1683 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1684 | szaddr = "0x%.08X" % value; 1685 | else: #is_x64(): 1686 | szaddr = "0x%.016lX" % value; 1687 | output("\033[1m%s :\033[0m %.04X %.04X %.04X %.04X %.04X %.04X %.04X %.04X \033[1m%s\033[0m" % (szaddr, 1688 | data[0], 1689 | data[1], 1690 | data[2], 1691 | data[3], 1692 | data[4], 1693 | data[5], 1694 | data[6], 1695 | data[7], 1696 | quotechars(membuff[index:index+0x10]))); 1697 | if index + 0x10 != 0x100: 1698 | output("\n"); 1699 | index += 0x10; 1700 | value += 0x10; 1701 | color_reset(); 1702 | result.PutCString("".join(GlobalListOutput)); 1703 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1704 | 1705 | def IphoneConnect(debugger, command, result, dict): 1706 | global GlobalListOutput; 1707 | GlobalListOutput = []; 1708 | 1709 | if len(command) == 0 or ":" not in command: 1710 | output("Connect to remote iPhone debug server"); 1711 | output("\n"); 1712 | output("iphone "); 1713 | output("\n"); 1714 | output("iphone 192.168.0.2:5555"); 1715 | result.PutCString("".join(GlobalListOutput)); 1716 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1717 | return; 1718 | 1719 | res = lldb.SBCommandReturnObject(); 1720 | lldb.debugger.GetCommandInterpreter().HandleCommand("platform select remote-ios", res); 1721 | if res.Succeeded() == True: 1722 | output(res.GetOutput()); 1723 | else: 1724 | output("Error running platform select remote-ios"); 1725 | result.PutCString("".join(GlobalListOutput)); 1726 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1727 | return; 1728 | lldb.debugger.GetCommandInterpreter().HandleCommand("process connect connect://" + command, res); 1729 | if res.Succeeded() == True: 1730 | output("Connected to iphone at : " + command); 1731 | else: 1732 | output(res.GetOutput()); 1733 | result.PutCString("".join(GlobalListOutput)); 1734 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1735 | 1736 | def findmem(debugger, command, result, dict): 1737 | global GlobalListOutput; 1738 | GlobalListOutput = []; 1739 | 1740 | arg = str(command); 1741 | parser = argparse.ArgumentParser(prog="lldb"); 1742 | parser.add_argument("-s", "--string", help="Search string"); 1743 | parser.add_argument("-u", "--unicode", help="Search unicode string"); 1744 | parser.add_argument("-b", "--binary", help="Serach binary string"); 1745 | parser.add_argument("-d", "--dword", help="Find dword (native packing)"); 1746 | parser.add_argument("-q", "--qword", help="Find qword (native packing)"); 1747 | parser.add_argument("-f", "--file" , help="Load find pattern from file"); 1748 | parser.add_argument("-c", "--count", help="How many occurances to find, default is all"); 1749 | 1750 | parser = parser.parse_args(arg.split()); 1751 | 1752 | if parser.string != None: 1753 | search_string = parser.string; 1754 | elif parser.unicode != None: 1755 | search_string = unicode(parser.unicode); 1756 | elif parser.binary != None: 1757 | search_string = parser.binary.decode("hex"); 1758 | elif parser.dword != None: 1759 | dword = evaluate(parser.dword); 1760 | if dword == None: 1761 | print("Error evaluating : " + parser.dword); 1762 | return; 1763 | search_string = struct.pack("I", dword & 0xffffffff); 1764 | elif parser.qword != None: 1765 | qword = evaluate(parser.qword); 1766 | if qword == None: 1767 | print("Error evaluating : " + parser.qword); 1768 | return; 1769 | search_string = struct.pack("Q", qword & 0xffffffffffffffff); 1770 | elif parser.file != None: 1771 | f = 0; 1772 | try: 1773 | f = open(parser.file, "rb"); 1774 | except: 1775 | print("Failed to open file : " + parser.file); 1776 | return; 1777 | search_string = f.read(); 1778 | f.close(); 1779 | else: 1780 | print("Wrong option... use findmem --help"); 1781 | return; 1782 | 1783 | count = -1; 1784 | if parser.count != None: 1785 | count = evaluate(parser.count); 1786 | if count == None: 1787 | print("Error evaluating count : " + parser.count); 1788 | return; 1789 | 1790 | process = lldb.debugger.GetSelectedTarget().GetProcess(); 1791 | pid = process.GetProcessID(); 1792 | output_data = subprocess.check_output(["/usr/bin/vmmap", "%d" % pid]) 1793 | lines = output_data.split("\n"); 1794 | #print(lines); 1795 | #this relies on output from /usr/bin/vmmap so code is dependant on that 1796 | #only reason why it's used is for better description of regions, which is 1797 | #nice to have. If they change vmmap in the future, I'll use my version 1798 | #and that output is much easier to parse... 1799 | newlines = []; 1800 | for x in lines: 1801 | p = re.compile("([\S\s]+)\s([\da-fA-F]{16}-[\da-fA-F]{16}|[\da-fA-F]{8}-[\da-fA-F]{8})"); 1802 | m = p.search(x); 1803 | if not m: continue; 1804 | tmp = []; 1805 | mem_name = m.group(1); 1806 | mem_range = m.group(2); 1807 | mem_start = long(mem_range.split("-")[0], 16); #0x000000-0x000000 1808 | mem_end = long(mem_range.split("-")[1], 16); 1809 | tmp.append(mem_name); 1810 | tmp.append(mem_start); 1811 | tmp.append(mem_end); 1812 | newlines.append(tmp); 1813 | 1814 | lines = sorted(newlines, key=lambda sortnewlines: sortnewlines[1]); 1815 | #move line extraction a bit up, thus we can latter sort it, as vmmap gives 1816 | #readable pages only, and then writable pages, so it looks ugly a bit :) 1817 | newlines = []; 1818 | for x in lines: 1819 | mem_name = x[0]; 1820 | mem_start= x[1]; 1821 | mem_end = x[2]; 1822 | mem_size = mem_end - mem_start; 1823 | 1824 | err = lldb.SBError(); 1825 | 1826 | membuff = process.ReadMemory(mem_start, mem_size, err); 1827 | if err.Success() == False: 1828 | #output(str(err)); 1829 | #result.PutCString("".join(GlobalListOutput)); 1830 | continue; 1831 | off = 0; 1832 | base_displayed = 0; 1833 | 1834 | while True: 1835 | if count == 0: return; 1836 | idx = membuff.find(search_string); 1837 | if idx == -1: break; 1838 | if count != -1: 1839 | count = count - 1; 1840 | off += idx; 1841 | 1842 | GlobalListOutput = []; 1843 | 1844 | if get_pointer_size() == 4: 1845 | ptrformat = "%.08X"; 1846 | else: 1847 | ptrformat = "%.016lX"; 1848 | 1849 | color_reset(); 1850 | output("Found at : "); 1851 | color(GREEN); 1852 | output(ptrformat % (mem_start + off)); 1853 | color_reset(); 1854 | if base_displayed == 0: 1855 | output(" base : "); 1856 | color(YELLOW); 1857 | output(ptrformat % mem_start); 1858 | color_reset(); 1859 | base_displayed = 1; 1860 | else: 1861 | output(" "); 1862 | if get_pointer_size() == 4: 1863 | output(" " * 8); 1864 | else: 1865 | output(" " * 16); 1866 | #well if somebody allocated 4GB of course offset will be to small to fit here 1867 | #but who cares... 1868 | output(" off : %.08X %s" % (off, mem_name)); 1869 | print("".join(GlobalListOutput)); 1870 | membuff = membuff[idx+len(search_string):]; 1871 | off += len(search_string); 1872 | return; 1873 | -------------------------------------------------------------------------------- /lldbinitpy3.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Similar implementation of .gdbinit from fG! for lldb in python 3 | 4 | How to install it: 5 | cp lldbinit.py /Library/Python/2.7/site-packages 6 | in $HOME/.lldbinit add: 7 | command script import lldbinit 8 | 9 | If you want latest lldb, to compile it from svn we need to do: 10 | svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb 11 | xcodebuild -configuration Release 12 | 13 | Commands which are implemented: 14 | stepo - step over some instructions (call/movs/stos/cmps/loop) 15 | dd - dump hex data at certain address (keep compatibility with .gdbinit) 16 | this shoud be db command 17 | ctx/context - dump registers and assembly 18 | lb - load breakpoints from file and apply them (currently only func names are applied) 19 | lb_rva - load breakpoints from file and apply to main executable, only RVA in this case 20 | and command will determine main program base and apply breaks 21 | u - dump instructions at certain address (SoftICE like u command style) 22 | ddword - dump data as dword 23 | dq - dump data as qword 24 | dw - dump data as word 25 | iphone - connect to debugserver running on iPhone 26 | findmem - command to search memory 27 | [options] 28 | -s searches for specified string 29 | -u searches for specified unicode string 30 | -b searches binary (eg. -b 4142434445 will find ABCDE anywhere in mem) 31 | -d searches dword (eg. -d 0x41414141) 32 | -q searches qword (eg. -d 0x4141414141414141) 33 | -f loads patern from file if it's tooooo big to fit into any of specified 34 | options 35 | -c specify if you want to find N occurances (default is all) 36 | bt - broken... and removed, now thread/frame information is by default shown on every 37 | hook-stop by lldb itself... 38 | 39 | hook-stop can be added only when target exists, before it's not possible (maybe in later versions 40 | of lldb it is or will be possible but...). Trick to get arround this is to create thread which will 41 | try to add hook-stop, and will continue doing so until it's done. This could cause some raise conditions 42 | as I don't know if this is thread safe, however in my testing (and using it) it worked quite well so 43 | I keep using it instead of adding extra command "init" or such when target is created... 44 | 45 | Currently registers dump are done for i386/x86_64/arm 46 | 47 | For supported ARM types for iPhone check here: 48 | source/Plugins/Platform/MacOSX/PlatformDarwin.cpp 49 | PlatformDarwin::ARMGetSupportedArchitectureAtIndex <-- maybe wrong, but you have 50 | idea what they support 51 | 52 | ''' 53 | 54 | if __name__ == "__main__": 55 | print("Run only as script from lldb... Not as standalone program"); 56 | 57 | try: 58 | import lldb 59 | except: 60 | pass; 61 | import sys 62 | import re 63 | import os 64 | import _thread 65 | import time 66 | import struct 67 | import argparse 68 | import subprocess 69 | 70 | old_eax = 0; 71 | old_ecx = 0; 72 | old_edx = 0; 73 | old_ebx = 0; 74 | old_esp = 0; 75 | old_ebp = 0; 76 | old_esi = 0; 77 | old_edi = 0; 78 | old_eip = 0; 79 | old_eflags = 0; 80 | old_cs = 0; 81 | old_ds = 0; 82 | old_fs = 0; 83 | old_gs = 0; 84 | old_ss = 0; 85 | old_es = 0; 86 | 87 | old_rax = 0; 88 | old_rcx = 0; 89 | old_rdx = 0; 90 | old_rbx = 0; 91 | old_rsp = 0; 92 | old_rbp = 0; 93 | old_rsi = 0; 94 | old_rdi = 0; 95 | old_r8 = 0; 96 | old_r9 = 0; 97 | old_r10 = 0; 98 | old_r11 = 0; 99 | old_r12 = 0; 100 | old_r13 = 0; 101 | old_r14 = 0; 102 | old_r15 = 0; 103 | old_rflags = 0; 104 | old_rip = 0; 105 | 106 | old_arm_r0 = 0; 107 | old_arm_r1 = 0; 108 | old_arm_r2 = 0; 109 | old_arm_r3 = 0; 110 | old_arm_r4 = 0; 111 | old_arm_r5 = 0; 112 | old_arm_r6 = 0; 113 | old_arm_r7 = 0; 114 | old_arm_r8 = 0; 115 | old_arm_r9 = 0; 116 | old_arm_r10 = 0; 117 | old_arm_r11 = 0; 118 | old_arm_r12 = 0; 119 | old_arm_sp = 0; 120 | old_arm_lr = 0; 121 | old_arm_pc = 0; 122 | old_arm_cpsr = 0; 123 | 124 | BLACK = 0 125 | RED = 1 126 | GREEN = 2 127 | YELLOW = 3 128 | BLUE = 4 129 | MAGENTA = 5 130 | CYAN = 6 131 | WHITE = 7 132 | 133 | COLOR_REGNAME = GREEN 134 | COLOR_REGVAL = WHITE 135 | COLOR_REGVAL_MODIFIED = RED 136 | COLOR_SEPARATOR = BLUE 137 | COLOR_CPUFLAGS = RED 138 | COLOR_HIGHLIGHT_LINE = CYAN 139 | 140 | arm_type = "thumbv7-apple-ios"; 141 | 142 | GlobalListOutput = []; 143 | 144 | hook_stop_added = 0; 145 | 146 | def wait_for_hook_stop(): 147 | while True: 148 | #print("Waiting..."); 149 | res = lldb.SBCommandReturnObject(); 150 | lldb.debugger.GetCommandInterpreter().HandleCommand("target stop-hook add -o \"HandleHookStopOnTarget\"", res); 151 | if res.Succeeded() == True: 152 | return; 153 | time.sleep(0.05); 154 | 155 | def __lldb_init_module(debugger, internal_dict): 156 | ''' we can execute commands using debugger.HandleCommand which makes all outptu to default 157 | lldb console. With GetCommandinterpreter().HandleCommand() we can consume all output 158 | with SBCommandReturnObject and parse data before we send it to output (eg. modify it); 159 | ''' 160 | global hook_stop_added; 161 | 162 | ''' 163 | If I'm running from $HOME where .lldbinit is located, seems like lldb will load 164 | .lldbinit 2 times, thus this dirty hack is here to prevent doulbe loading... 165 | if somebody knows better way, would be great to know :) 166 | ''' 167 | var = lldb.debugger.GetInternalVariableValue("stop-disassembly-count", lldb.debugger.GetInstanceName()); 168 | if var.IsValid(): 169 | var = var.GetStringAtIndex(0); 170 | if var == "0": 171 | return; 172 | res = lldb.SBCommandReturnObject(); 173 | 174 | lldb.debugger.GetCommandInterpreter().HandleCommand("settings set target.x86-disassembly-flavor intel", res); 175 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.stepo stepo", res); 176 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.HandleHookStopOnTarget HandleHookStopOnTarget", res); 177 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.dd dd", res); 178 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.si si", res); 179 | #lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.r r", res); 180 | #lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.r run", res); 181 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.HandleHookStopOnTarget ctx", res); 182 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.HandleHookStopOnTarget context", res); 183 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.DumpInstructions u", res); 184 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.LoadBreakPoints lb", res); 185 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.LoadBreakPointsRva lbrva", res); 186 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.dq dq", res); 187 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.dd db", res); 188 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.ddword ddword", res); 189 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.dw dw", res); 190 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.IphoneConnect iphone", res); 191 | lldb.debugger.GetCommandInterpreter().HandleCommand("command script add -f lldbinit.findmem findmem", res); 192 | 193 | 194 | ''' 195 | target stop-hook can be added only when target is loaded, thus I create thread 196 | to execute this command until it returns success... dunno if this is ok, or thread 197 | safe, but I hate to add extra command "init" or such to install this hook... 198 | ''' 199 | _thread.start_new_thread(wait_for_hook_stop, ()); 200 | 201 | #lldb.debugger.GetCommandInterpreter().HandleCommand("settings set prompt \"\033[01;31m(lldb) \033[0m\"", res); 202 | lldb.debugger.GetCommandInterpreter().HandleCommand("settings set stop-disassembly-count 0", res); 203 | return; 204 | 205 | 206 | def get_arch(): 207 | return lldb.debugger.GetSelectedTarget().triple.split('-')[0]; 208 | def get_frame(): 209 | #return lldb.debugger.GetSelectedTarget().process.selected_thread.GetSelectedFrame(); 210 | #return lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() 211 | #return lldb.debugger.GetTargetAtIndex(0).process.selected_thread.GetFrameAtIndex(0); 212 | 213 | #return frame for stopped thread... there should be one at least... 214 | ret = None; 215 | for t in get_process(): 216 | if t.GetStopReason() != lldb.eStopReasonNone and t.GetStopReason() != lldb.eStopReasonInvalid: 217 | ret = t.GetFrameAtIndex(0); 218 | 219 | return ret; 220 | 221 | def get_process(): 222 | return lldb.debugger.GetSelectedTarget().process; #GetTargetAtIndex(0).process; 223 | 224 | def evaluate(command): 225 | value = get_frame().EvaluateExpression(command); 226 | if value.IsValid() == False: 227 | return None; 228 | try: 229 | value = int(value.GetValue(), 10); #long(value.GetValue(), 10); 230 | return value; 231 | except: 232 | try: 233 | value = int(value.GetValue(), 16); 234 | return value; 235 | except: 236 | 237 | return None; 238 | 239 | def is_i386(): 240 | arch = get_arch(); 241 | if arch[0:1] == "i": 242 | return True; 243 | return False; 244 | 245 | def is_x64(): 246 | arch = get_arch(); 247 | if arch == "x86_64": 248 | return True; 249 | return False; 250 | 251 | def is_arm(): 252 | arch = get_arch(); 253 | if "arm" in arch: 254 | return True; 255 | return False; 256 | 257 | def get_pointer_size(): 258 | poisz = evaluate("sizeof(long)"); 259 | return poisz; 260 | 261 | def color_reset(): 262 | output("\033[0m"); 263 | def color_bold(): 264 | output("\033[1m"); 265 | def color_underline(): 266 | output("\033[4m"); 267 | 268 | def color(x): 269 | out_col = ""; 270 | if x == BLACK: 271 | out_col = "\033[30m"; 272 | elif x == RED: 273 | out_col = "\033[31m"; 274 | elif x == GREEN: 275 | out_col = "\033[32m"; 276 | elif x == YELLOW: 277 | out_col = "\033[33m"; 278 | elif x == BLUE: 279 | out_col = "\033[34m"; 280 | elif x == MAGENTA: 281 | out_col = "\033[35m"; 282 | elif x == CYAN: 283 | out_col = "\033[36m"; 284 | elif x == WHITE: 285 | out_col = "\033[37m"; 286 | output(out_col); 287 | 288 | def output(x): 289 | global GlobalListOutput; 290 | GlobalListOutput.append(x); 291 | 292 | def get_register(reg_name): 293 | regs = get_GPRs(); 294 | if regs == None: 295 | return "0"; 296 | for reg in regs: 297 | if reg_name == reg.GetName(): 298 | return reg.GetValue(); 299 | return "0"; #0; 300 | 301 | def get_registers(kind): 302 | """Returns the registers given the frame and the kind of registers desired. 303 | 304 | Returns None if there's no such kind. 305 | """ 306 | registerSet = get_frame().GetRegisters() # Return type of SBValueList. 307 | for value in registerSet: 308 | if kind.lower() in value.GetName().lower(): 309 | return value 310 | 311 | return None 312 | 313 | def dump_eflags(eflags): 314 | if (eflags >> 0xB) & 1: 315 | output("O "); 316 | else: 317 | output("o "); 318 | 319 | if (eflags >> 0xA) & 1: 320 | output("D "); 321 | else: 322 | output("d "); 323 | 324 | if (eflags >> 9) & 1: 325 | output("I "); 326 | else: 327 | output("i "); 328 | 329 | if (eflags >> 8) & 1: 330 | output("T "); 331 | else: 332 | output("t "); 333 | 334 | if (eflags >> 7) & 1: 335 | output("S "); 336 | else: 337 | output("s "); 338 | 339 | if (eflags >> 6) & 1: 340 | output("Z "); 341 | else: 342 | output("z "); 343 | 344 | if (eflags >> 4) & 1: 345 | output("A "); 346 | else: 347 | output("a "); 348 | 349 | if (eflags >> 2) & 1: 350 | output("P "); 351 | else: 352 | output("p "); 353 | 354 | if eflags & 1: 355 | output("C"); 356 | else: 357 | output("c"); 358 | 359 | def reg64(): 360 | global old_cs; 361 | global old_ds; 362 | global old_fs; 363 | global old_gs; 364 | global old_ss; 365 | global old_es; 366 | global old_rax; 367 | global old_rcx; 368 | global old_rdx; 369 | global old_rbx; 370 | global old_rsp; 371 | global old_rbp; 372 | global old_rsi; 373 | global old_rdi; 374 | global old_r8; 375 | global old_r9; 376 | global old_r10; 377 | global old_r11; 378 | global old_r12; 379 | global old_r13; 380 | global old_r14; 381 | global old_r15; 382 | global old_rflags; 383 | global old_rip; 384 | 385 | rax = int(str(get_register("rax")).strip().split()[0], 16); 386 | rcx = int(str(get_register("rcx")).strip().split()[0], 16); 387 | rdx = int(str(get_register("rdx")).strip().split()[0], 16); 388 | rbx = int(str(get_register("rbx")).strip().split()[0], 16); 389 | rsp = int(str(get_register("rsp")).strip().split()[0], 16); 390 | rbp = int(str(get_register("rbp")).strip().split()[0], 16); 391 | rsi = int(str(get_register("rsi")).strip().split()[0], 16); 392 | rdi = int(str(get_register("rdi")).strip().split()[0], 16); 393 | r8 = int(str(get_register("r8")).strip().split()[0], 16); 394 | r9 = int(str(get_register("r9")).strip().split()[0], 16); 395 | r10 = int(str(get_register("r10")).strip().split()[0], 16); 396 | r11 = int(str(get_register("r11")).strip().split()[0], 16); 397 | r12 = int(str(get_register("r12")).strip().split()[0], 16); 398 | r13 = int(str(get_register("r13")).strip().split()[0], 16); 399 | r14 = int(str(get_register("r14")).strip().split()[0], 16); 400 | r15 = int(str(get_register("r15")).strip().split()[0], 16); 401 | rip = int(str(get_register("rip")).strip().split()[0], 16); 402 | rflags = int(str(get_register("rflags")).strip().split()[0], 16); 403 | cs = int(str(get_register("cs")).strip().split()[0], 16); 404 | gs = int(str(get_register("gs")).strip().split()[0], 16); 405 | fs = int(str(get_register("fs")).strip().split()[0], 16); 406 | 407 | # not needed as x64 doesn't use them... 408 | # ds = int(str(get_register("ds")).strip().split()[0], 16); 409 | # ss = int(str(get_register("ss")).strip().split()[0], 16); 410 | 411 | color(COLOR_REGNAME); 412 | output(" RAX: "); 413 | if rax == old_rax: 414 | color(COLOR_REGVAL); 415 | else: 416 | color(COLOR_REGVAL_MODIFIED); 417 | output("0x%.016lX" % (rax)); 418 | old_rax = rax; 419 | 420 | color(COLOR_REGNAME); 421 | output(" RBX: ") 422 | if rbx == old_rbx: 423 | color(COLOR_REGVAL); 424 | else: 425 | color(COLOR_REGVAL_MODIFIED); 426 | output("0x%.016lX" % (rbx)); 427 | old_rbx = rbx; 428 | 429 | color(COLOR_REGNAME); 430 | output(" RBP: "); 431 | if rbp == old_rbp: 432 | color(COLOR_REGVAL); 433 | else: 434 | color(COLOR_REGVAL_MODIFIED); 435 | output("0x%.016lX" % (rbp)); 436 | old_rbp = rbp; 437 | 438 | color(COLOR_REGNAME); 439 | output(" RSP: "); 440 | if rsp == old_rsp: 441 | color(COLOR_REGVAL); 442 | else: 443 | color(COLOR_REGVAL_MODIFIED); 444 | output("0x%.016lX" % (rsp)); 445 | old_rsp = rsp; 446 | 447 | output(" "); 448 | color_bold(); 449 | color_underline(); 450 | color(COLOR_CPUFLAGS); 451 | dump_eflags(rflags); 452 | color_reset(); 453 | 454 | output("\n"); 455 | 456 | 457 | color(COLOR_REGNAME); 458 | output(" RDI: "); 459 | if rdi == old_rdi: 460 | color(COLOR_REGVAL); 461 | else: 462 | color(COLOR_REGVAL_MODIFIED); 463 | output("0x%.016lX" % (rdi)); 464 | old_rdi = rdi; 465 | 466 | color(COLOR_REGNAME); 467 | output(" RSI: "); 468 | if rsi == old_rsi: 469 | color(COLOR_REGVAL); 470 | else: 471 | color(COLOR_REGVAL_MODIFIED); 472 | output("0x%.016lX" % (rsi)); 473 | old_rsi = rsi; 474 | 475 | color(COLOR_REGNAME); 476 | output(" RDX: "); 477 | if rdx == old_rdx: 478 | color(COLOR_REGVAL); 479 | else: 480 | color(COLOR_REGVAL_MODIFIED); 481 | output("0x%.016lX" % (rdx)); 482 | old_rdx = rdx; 483 | 484 | color(COLOR_REGNAME); 485 | output(" RCX: "); 486 | if rcx == old_rcx: 487 | color(COLOR_REGVAL); 488 | else: 489 | color(COLOR_REGVAL_MODIFIED); 490 | output("0x%.016lX" % (rcx)); 491 | old_rcx = rcx; 492 | 493 | color(COLOR_REGNAME); 494 | output(" RIP: "); 495 | if rip == old_rip: 496 | color(COLOR_REGVAL); 497 | else: 498 | color(COLOR_REGVAL_MODIFIED); 499 | output("0x%.016lX" % (rip)); 500 | old_rip = rip; 501 | output("\n"); 502 | 503 | color(COLOR_REGNAME); 504 | output(" R8: "); 505 | if r8 == old_r8: 506 | color(COLOR_REGVAL); 507 | else: 508 | color(COLOR_REGVAL_MODIFIED); 509 | output("0x%.016lX" % (r8)); 510 | old_r8 = r8; 511 | 512 | color(COLOR_REGNAME); 513 | output(" R9: "); 514 | if r9 == old_r9: 515 | color(COLOR_REGVAL); 516 | else: 517 | color(COLOR_REGVAL_MODIFIED); 518 | output("0x%.016lX" % (r9)); 519 | old_r9 = r9; 520 | 521 | color(COLOR_REGNAME); 522 | output(" R10: "); 523 | if r10 == old_r10: 524 | color(COLOR_REGVAL); 525 | else: 526 | color(COLOR_REGVAL_MODIFIED); 527 | output("0x%.016lX" % (r10)); 528 | old_r10 = r10; 529 | 530 | color(COLOR_REGNAME); 531 | output(" R11: "); 532 | if r11 == old_r11: 533 | color(COLOR_REGVAL); 534 | else: 535 | color(COLOR_REGVAL_MODIFIED); 536 | output("0x%.016lX" % (r11)); 537 | old_r11 = r11; 538 | 539 | color(COLOR_REGNAME); 540 | output(" R12: "); 541 | if r12 == old_r12: 542 | color(COLOR_REGVAL); 543 | else: 544 | color(COLOR_REGVAL_MODIFIED); 545 | output("0x%.016lX" % (r12)); 546 | old_r12 = r12; 547 | 548 | output("\n"); 549 | 550 | color(COLOR_REGNAME); 551 | output(" R13: "); 552 | if r13 == old_r13: 553 | color(COLOR_REGVAL); 554 | else: 555 | color(COLOR_REGVAL_MODIFIED); 556 | output("0x%.016lX" % (r13)); 557 | old_r13 = r13; 558 | 559 | color(COLOR_REGNAME); 560 | output(" R14: "); 561 | if r14 == old_r14: 562 | color(COLOR_REGVAL); 563 | else: 564 | color(COLOR_REGVAL_MODIFIED); 565 | output("0x%.016lX" % (r14)); 566 | old_r14 = r14; 567 | 568 | color(COLOR_REGNAME); 569 | output(" R15: "); 570 | if r15 == old_r15: 571 | color(COLOR_REGVAL); 572 | else: 573 | color(COLOR_REGVAL_MODIFIED); 574 | output("0x%.016lX" % (r15)); 575 | old_r15 = r15; 576 | output("\n"); 577 | 578 | color(COLOR_REGNAME); 579 | output(" CS: "); 580 | if cs == old_cs: 581 | color(COLOR_REGVAL); 582 | else: 583 | color(COLOR_REGVAL_MODIFIED); 584 | output("%.04X" % (cs)); 585 | old_cs = cs; 586 | 587 | color(COLOR_REGNAME); 588 | output(" FS: "); 589 | if fs == old_fs: 590 | color(COLOR_REGVAL); 591 | else: 592 | color(COLOR_REGVAL_MODIFIED); 593 | output("%.04X" % (fs)); 594 | old_fs = fs; 595 | 596 | color(COLOR_REGNAME); 597 | output(" GS: "); 598 | if gs == old_gs: 599 | color(COLOR_REGVAL); 600 | else: 601 | color(COLOR_REGVAL_MODIFIED); 602 | output("%.04X" % (gs)); 603 | old_gs = gs; 604 | output("\n"); 605 | 606 | def reg32(): 607 | global old_eax; 608 | global old_ecx; 609 | global old_edx; 610 | global old_ebx; 611 | global old_esp; 612 | global old_ebp; 613 | global old_esi; 614 | global old_edi; 615 | global old_eflags; 616 | global old_cs; 617 | global old_ds; 618 | global old_fs; 619 | global old_gs; 620 | global old_ss; 621 | global old_es; 622 | global old_eip; 623 | 624 | color(COLOR_REGNAME); 625 | output(" EAX: "); 626 | eax = int(get_register("eax"), 16); 627 | if eax == old_eax: 628 | color(COLOR_REGVAL); 629 | else: 630 | color(COLOR_REGVAL_MODIFIED); 631 | output("0x%.08X" % (eax)); 632 | old_eax = eax; 633 | 634 | color(COLOR_REGNAME); 635 | output(" EBX: "); 636 | ebx = int(get_register("ebx"), 16); 637 | if ebx == old_ebx: 638 | color(COLOR_REGVAL); 639 | else: 640 | color(COLOR_REGVAL_MODIFIED); 641 | output("0x%.08X" % (ebx)); 642 | old_ebx = ebx; 643 | 644 | color(COLOR_REGNAME); 645 | output(" ECX: "); 646 | ecx = int(get_register("ecx"), 16); 647 | if ecx == old_ecx: 648 | color(COLOR_REGVAL); 649 | else: 650 | color(COLOR_REGVAL_MODIFIED); 651 | output("0x%.08X" % (ecx)); 652 | old_ecx = ecx; 653 | 654 | color(COLOR_REGNAME); 655 | output(" EDX: "); 656 | edx = int(get_register("edx"), 16); 657 | if edx == old_edx: 658 | color(COLOR_REGVAL); 659 | else: 660 | color(COLOR_REGVAL_MODIFIED); 661 | output("0x%.08X" % (edx)); 662 | old_edx = edx; 663 | 664 | output(" "); 665 | eflags = int(get_register("eflags"), 16); 666 | color_bold(); 667 | color_underline(); 668 | color(COLOR_CPUFLAGS); 669 | dump_eflags(eflags); 670 | color_reset(); 671 | 672 | output("\n"); 673 | 674 | color(COLOR_REGNAME); 675 | output(" ESI: "); 676 | esi = int(get_register("esi"), 16); 677 | if esi == old_esi: 678 | color(COLOR_REGVAL); 679 | else: 680 | color(COLOR_REGVAL_MODIFIED); 681 | output("0x%.08X" % (esi)); 682 | old_esi = esi; 683 | 684 | color(COLOR_REGNAME); 685 | output(" EDI: "); 686 | edi = int(get_register("edi"), 16); 687 | if edi == old_edi: 688 | color(COLOR_REGVAL); 689 | else: 690 | color(COLOR_REGVAL_MODIFIED); 691 | output("0x%.08X" % (edi)); 692 | old_edi = edi; 693 | 694 | color(COLOR_REGNAME); 695 | output(" EBP: "); 696 | ebp = int(get_register("ebp"), 16); 697 | if ebp == old_ebp: 698 | color(COLOR_REGVAL); 699 | else: 700 | color(COLOR_REGVAL_MODIFIED); 701 | output("0x%.08X" % (ebp)); 702 | old_ebp = ebp; 703 | 704 | color(COLOR_REGNAME); 705 | output(" ESP: "); 706 | esp = int(get_register("esp"), 16); 707 | if esp == old_esp: 708 | color(COLOR_REGVAL); 709 | else: 710 | color(COLOR_REGVAL_MODIFIED); 711 | output("0x%.08X" % (esp)); 712 | old_esp = esp; 713 | 714 | color(COLOR_REGNAME); 715 | output(" EIP: "); 716 | eip = int(get_register("eip"), 16); 717 | if eip == old_eip: 718 | color(COLOR_REGVAL); 719 | else: 720 | color(COLOR_REGVAL_MODIFIED); 721 | output("0x%.08X" % (eip)); 722 | old_eip = eip; 723 | output("\n"); 724 | 725 | color(COLOR_REGNAME); 726 | output(" CS: "); 727 | cs = int(get_register("cs"), 16); 728 | if cs == old_cs: 729 | color(COLOR_REGVAL); 730 | else: 731 | color(COLOR_REGVAL_MODIFIED); 732 | output("%.04X" % (cs)); 733 | old_cs = cs; 734 | 735 | color(COLOR_REGNAME); 736 | output(" DS: "); 737 | ds = int(get_register("ds"), 16); 738 | if ds == old_ds: 739 | color(COLOR_REGVAL); 740 | else: 741 | color(COLOR_REGVAL_MODIFIED); 742 | output("%.04X" % (ds)); 743 | old_ds = ds; 744 | 745 | color(COLOR_REGNAME); 746 | output(" ES: "); 747 | es = int(get_register("es"), 16); 748 | if es == old_es: 749 | color(COLOR_REGVAL); 750 | else: 751 | color(COLOR_REGVAL_MODIFIED); 752 | output("%.04X" % (es)); 753 | old_es = es; 754 | 755 | color(COLOR_REGNAME); 756 | output(" FS: "); 757 | fs = int(get_register("fs"), 16); 758 | if fs == old_fs: 759 | color(COLOR_REGVAL); 760 | else: 761 | color(COLOR_REGVAL_MODIFIED); 762 | output("%.04X" % (fs)); 763 | old_fs = fs; 764 | 765 | color(COLOR_REGNAME); 766 | output(" GS: "); 767 | gs = int(get_register("gs"), 16); 768 | if gs == old_gs: 769 | color(COLOR_REGVAL); 770 | else: 771 | color(COLOR_REGVAL_MODIFIED); 772 | output("%.04X" % (gs)); 773 | old_gs = gs; 774 | 775 | color(COLOR_REGNAME); 776 | output(" SS: "); 777 | ss = int(get_register("ss"), 16); 778 | if ss == old_ss: 779 | color(COLOR_REGVAL); 780 | else: 781 | color(COLOR_REGVAL_MODIFIED); 782 | output("%.04X" % (ss)); 783 | old_ss = ss; 784 | output("\n"); 785 | 786 | def dump_cpsr(cpsr): 787 | if (cpsr >> 31) & 1: 788 | output("N "); 789 | else: 790 | output("n "); 791 | 792 | if (cpsr >> 30) & 1: 793 | output("Z "); 794 | else: 795 | output("z "); 796 | 797 | if (cpsr >> 29) & 1: 798 | output("C "); 799 | else: 800 | output("c "); 801 | 802 | if (cpsr >> 28) & 1: 803 | output("V "); 804 | else: 805 | output("v "); 806 | 807 | if (cpsr >> 27) & 1: 808 | output("Q "); 809 | else: 810 | output("q "); 811 | 812 | if (cpsr >> 24) & 1: 813 | output("J "); 814 | else: 815 | output("j "); 816 | 817 | if (cpsr >> 9) & 1: 818 | output("E "); 819 | else: 820 | output("e "); 821 | if (cpsr >> 8) & 1: 822 | output("A "); 823 | else: 824 | output("a "); 825 | if (cpsr >> 7) & 1: 826 | output("I "); 827 | else: 828 | output("i "); 829 | if (cpsr >> 6) & 1: 830 | output("F "); 831 | else: 832 | output("f "); 833 | if (cpsr >> 5) & 1: 834 | output("T"); 835 | else: 836 | output("t"); 837 | 838 | def regarm(): 839 | global old_arm_r0; 840 | global old_arm_r1; 841 | global old_arm_r2; 842 | global old_arm_r3; 843 | global old_arm_r4; 844 | global old_arm_r5; 845 | global old_arm_r6; 846 | global old_arm_r7; 847 | global old_arm_r8; 848 | global old_arm_r9; 849 | global old_arm_r10; 850 | global old_arm_r11; 851 | global old_arm_r12; 852 | global old_arm_sp; 853 | global old_arm_lr; 854 | global old_arm_pc; 855 | global old_arm_cpsr; 856 | 857 | color(COLOR_REGNAME); 858 | output(" R0: "); 859 | r0 = int(get_register("r0"), 16); 860 | if r0 == old_arm_r0: 861 | color(COLOR_REGVAL); 862 | else: 863 | color(COLOR_REGVAL_MODIFIED); 864 | output("0x%.08X" % (r0)); 865 | old_arm_r0 = r0; 866 | 867 | color(COLOR_REGNAME); 868 | output(" R1: "); 869 | r1 = int(get_register("r1"), 16); 870 | if r1 == old_arm_r1: 871 | color(COLOR_REGVAL); 872 | else: 873 | color(COLOR_REGVAL_MODIFIED); 874 | output("0x%.08X" % (r1)); 875 | old_arm_r1 = r1; 876 | 877 | color(COLOR_REGNAME); 878 | output(" R2: "); 879 | r2 = int(get_register("r2"), 16); 880 | if r2 == old_arm_r2: 881 | color(COLOR_REGVAL); 882 | else: 883 | color(COLOR_REGVAL_MODIFIED); 884 | output("0x%.08X" % (r2)); 885 | old_arm_r2 = r2; 886 | 887 | color(COLOR_REGNAME); 888 | output(" R3: "); 889 | r3 = int(get_register("r3"), 16); 890 | if r3 == old_arm_r3: 891 | color(COLOR_REGVAL); 892 | else: 893 | color(COLOR_REGVAL_MODIFIED); 894 | output("0x%.08X" % (r3)); 895 | old_arm_r3 = r3; 896 | 897 | output(" "); 898 | color_bold(); 899 | color_underline(); 900 | color(COLOR_CPUFLAGS); 901 | cpsr = int(get_register("cpsr"), 16); 902 | dump_cpsr(cpsr); 903 | color_reset(); 904 | 905 | output("\n"); 906 | 907 | 908 | color(COLOR_REGNAME); 909 | output(" R4: "); 910 | r4 = int(get_register("r4"), 16); 911 | if r4 == old_arm_r4: 912 | color(COLOR_REGVAL); 913 | else: 914 | color(COLOR_REGVAL_MODIFIED); 915 | output("0x%.08X" % (r4)); 916 | old_arm_r4 = r4; 917 | 918 | color(COLOR_REGNAME); 919 | output(" R5: "); 920 | r5 = int(get_register("r5"), 16); 921 | if r5 == old_arm_r5: 922 | color(COLOR_REGVAL); 923 | else: 924 | color(COLOR_REGVAL_MODIFIED); 925 | output("0x%.08X" % (r5)); 926 | old_arm_r5 = r5; 927 | 928 | color(COLOR_REGNAME); 929 | output(" R6: "); 930 | r6 = int(get_register("r6"), 16); 931 | if r6 == old_arm_r6: 932 | color(COLOR_REGVAL); 933 | else: 934 | color(COLOR_REGVAL_MODIFIED); 935 | output("0x%.08X" % (r6)); 936 | old_arm_r6 = r6; 937 | 938 | color(COLOR_REGNAME); 939 | output(" R7: "); 940 | r7 = int(get_register("r7"), 16); 941 | if r7 == old_arm_r7: 942 | color(COLOR_REGVAL); 943 | else: 944 | color(COLOR_REGVAL_MODIFIED); 945 | output("0x%.08X" % (r7)); 946 | old_arm_r7 = r7; 947 | 948 | output("\n"); 949 | 950 | color(COLOR_REGNAME); 951 | output(" R8: "); 952 | r8 = int(get_register("r8"), 16); 953 | if r8 == old_arm_r8: 954 | color(COLOR_REGVAL); 955 | else: 956 | color(COLOR_REGVAL_MODIFIED); 957 | output("0x%.08X" % (r8)); 958 | old_arm_r8 = r8; 959 | 960 | color(COLOR_REGNAME); 961 | output(" R9: "); 962 | r9 = int(get_register("r9"), 16); 963 | if r9 == old_arm_r9: 964 | color(COLOR_REGVAL); 965 | else: 966 | color(COLOR_REGVAL_MODIFIED); 967 | output("0x%.08X" % (r9)); 968 | old_arm_r9 = r9; 969 | 970 | color(COLOR_REGNAME); 971 | output(" R10: "); 972 | r10 = int(get_register("r10"), 16); 973 | if r10 == old_arm_r10: 974 | color(COLOR_REGVAL); 975 | else: 976 | color(COLOR_REGVAL_MODIFIED); 977 | output("0x%.08X" % (r10)); 978 | old_arm_r10 = r10; 979 | 980 | color(COLOR_REGNAME); 981 | output(" R11: "); 982 | r11 = int(get_register("r11"), 16); 983 | if r11 == old_arm_r11: 984 | color(COLOR_REGVAL); 985 | else: 986 | color(COLOR_REGVAL_MODIFIED); 987 | output("0x%.08X" % (r11)); 988 | old_arm_r11 = r11; 989 | 990 | output("\n"); 991 | 992 | color(COLOR_REGNAME); 993 | output(" R12: "); 994 | r12 = int(get_register("r12"), 16); 995 | if r12 == old_arm_r12: 996 | color(COLOR_REGVAL); 997 | else: 998 | color(COLOR_REGVAL_MODIFIED); 999 | output("0x%.08X" % (r12)); 1000 | old_arm_r12 = r12; 1001 | 1002 | color(COLOR_REGNAME); 1003 | output(" SP: "); 1004 | sp = int(get_register("sp"), 16); 1005 | if sp == old_arm_sp: 1006 | color(COLOR_REGVAL); 1007 | else: 1008 | color(COLOR_REGVAL_MODIFIED); 1009 | output("0x%.08X" % (sp)); 1010 | old_arm_sp = sp; 1011 | 1012 | color(COLOR_REGNAME); 1013 | output(" LR: "); 1014 | lr = int(get_register("lr"), 16); 1015 | if lr == old_arm_lr: 1016 | color(COLOR_REGVAL); 1017 | else: 1018 | color(COLOR_REGVAL_MODIFIED); 1019 | output("0x%.08X" % (lr)); 1020 | old_arm_lr = lr; 1021 | 1022 | color(COLOR_REGNAME); 1023 | output(" PC: "); 1024 | pc = int(get_register("pc"), 16); 1025 | if pc == old_arm_pc: 1026 | color(COLOR_REGVAL); 1027 | else: 1028 | color(COLOR_REGVAL_MODIFIED); 1029 | output("0x%.08X" % (pc)); 1030 | old_arm_pc = pc; 1031 | output("\n"); 1032 | 1033 | def print_registers(): 1034 | arch = get_arch(); 1035 | if is_i386(): 1036 | reg32(); 1037 | elif is_x64(): 1038 | reg64(); 1039 | elif is_arm(): 1040 | regarm(); 1041 | def get_GPRs(): 1042 | """Returns the general purpose registers of the frame as an SBValue. 1043 | 1044 | The returned SBValue object is iterable. An example: 1045 | ... 1046 | from lldbutil import get_GPRs 1047 | regs = get_GPRs(frame) 1048 | for reg in regs: 1049 | print "%s => %s" % (reg.GetName(), reg.GetValue()) 1050 | ... 1051 | """ 1052 | return get_registers("general purpose") 1053 | 1054 | def HandleHookStopOnTarget(debugger, command, result, dict): 1055 | # Don't display anything if we're inside Xcode 1056 | if os.getenv('PATH').startswith('/Applications/Xcode.app'): 1057 | return 1058 | 1059 | global GlobalListOutput; 1060 | global arm_type; 1061 | 1062 | debugger.SetAsync(True); 1063 | frame = get_frame(); 1064 | if not frame: return; 1065 | 1066 | thread= frame.GetThread(); 1067 | while True: 1068 | frame = get_frame(); 1069 | thread = frame.GetThread(); 1070 | #print("----------------------------------"); 1071 | #for t in get_process(): 1072 | # print("Thread stop reason : %d" % (t.GetStopReason())); 1073 | 1074 | if thread.GetStopReason() == lldb.eStopReasonNone or thread.GetStopReason() == lldb.eStopReasonInvalid: 1075 | time.sleep(0.001); 1076 | else: 1077 | break; 1078 | 1079 | GlobalListOutput = []; 1080 | 1081 | arch = get_arch(); 1082 | if not is_i386() and not is_x64() and not is_arm(): 1083 | #this is for ARM probably in the future... when I will need it... 1084 | print("Unknown architecture : " + arch); 1085 | return; 1086 | 1087 | output("\n"); 1088 | color(COLOR_SEPARATOR); 1089 | if is_i386() or is_arm(): 1090 | output("---------------------------------------------------------------------------------"); 1091 | elif is_x64(): 1092 | output("-----------------------------------------------------------------------------------------------------------------------"); 1093 | 1094 | color_bold(); 1095 | output("[regs]\n"); 1096 | color_reset(); 1097 | print_registers(); 1098 | 1099 | color(COLOR_SEPARATOR); 1100 | if is_i386() or is_arm(): 1101 | output("---------------------------------------------------------------------------------"); 1102 | elif is_x64(): 1103 | output("-----------------------------------------------------------------------------------------------------------------------"); 1104 | color_bold(); 1105 | output("[code]\n"); 1106 | color_reset(); 1107 | 1108 | if is_i386(): 1109 | pc = get_register("eip"); 1110 | elif is_x64(): 1111 | pc = get_register("rip"); 1112 | elif is_arm(): 1113 | pc = get_register("pc"); 1114 | 1115 | res = lldb.SBCommandReturnObject(); 1116 | if is_arm(): 1117 | cpsr = int(get_register("cpsr"), 16); 1118 | t = (cpsr >> 5) & 1; 1119 | if t: 1120 | #it's thumb 1121 | arm_type = "thumbv7-apple-ios"; 1122 | else: 1123 | arm_type = "armv7-apple-ios"; 1124 | lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble -A " + arm_type + " --start-address=" + pc + " --count=8", res) 1125 | else: 1126 | lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble --start-address=" + pc + " --count=8", res); 1127 | data = res.GetOutput(); 1128 | #split lines... and mark currently executed code... 1129 | data = data.split("\n"); 1130 | #detemine what to hl, as sometimes lldb won't put => into stoped thread... well... 1131 | #need to check if first sym is => or ' ' which means this is name without symol 1132 | #symbols are stored 1st so here we go... 1133 | line_to_hl = 0; 1134 | #if data[0][0:2] == "->": 1135 | # line_to_hl = 0; 1136 | #if data[0][0:2] != ' ': 1137 | # line_to_hl = 1; 1138 | 1139 | #now we look when pc is held in disassembly and we color only that line 1140 | pc_text = int(str(pc).strip().split()[0], 16); 1141 | pc_text = hex(pc_text); 1142 | #print(pc_text); 1143 | for idx,x in enumerate(data): 1144 | if pc_text in x: 1145 | line_to_hl = idx; 1146 | break; 1147 | for idx,x in enumerate(data): 1148 | if line_to_hl == idx: #x[0:2] == "->" and idx < 3: 1149 | color(COLOR_HIGHLIGHT_LINE); 1150 | color_bold(); 1151 | output(x); 1152 | color_reset(); 1153 | else: 1154 | output(x); 1155 | output("\n"); 1156 | #output(res.GetOutput()); 1157 | color(COLOR_SEPARATOR); 1158 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1159 | output("---------------------------------------------------------------------------------------"); 1160 | elif get_pointer_size() == 8: #is_x64(): 1161 | output("-----------------------------------------------------------------------------------------------------------------------------"); 1162 | color_reset(); 1163 | output("\n"); 1164 | 1165 | output("Stop reason : " + str(thread.GetStopDescription(100))); #str(lldb.debugger.GetSelectedTarget().process.selected_thread.GetStopDescription(100))); 1166 | output("\r"); 1167 | data = "".join(GlobalListOutput); 1168 | 1169 | result.PutCString(data); 1170 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1171 | return 0; 1172 | 1173 | def LoadBreakPointsRva(debugger, command, result, dict): 1174 | global GlobalOutputList; 1175 | GlobalOutputList = []; 1176 | ''' 1177 | frame = get_frame(); 1178 | target = lldb.debugger.GetSelectedTarget(); 1179 | 1180 | nummods = target.GetNumModules(); 1181 | #for x in range (0, nummods): 1182 | # mod = target.GetModuleAtIndex(x); 1183 | # #print(dir(mod)); 1184 | # print(target.GetModuleAtIndex(x)); 1185 | # for sec in mod.section_iter(): 1186 | # addr = sec.GetLoadAddress(target); 1187 | # name = sec.GetName(); 1188 | # print(hex(addr)); 1189 | 1190 | #1st module is executable 1191 | mod = target.GetModuleAtIndex(0); 1192 | sec = mod.GetSectionAtIndex(0); 1193 | loadaddr = sec.GetLoadAddress(target); 1194 | if loadaddr == lldb.LLDB_INVALID_ADDRESS: 1195 | sec = mod.GetSectionAtIndex(1); 1196 | loadaddr = sec.GetLoadAddress(target); 1197 | print(hex(loadaddr)); 1198 | ''' 1199 | 1200 | target = lldb.debugger.GetSelectedTarget(); 1201 | mod = target.GetModuleAtIndex(0); 1202 | sec = mod.GetSectionAtIndex(0); 1203 | loadaddr = sec.GetLoadAddress(target); 1204 | if loadaddr == lldb.LLDB_INVALID_ADDRESS: 1205 | sec = mod.GetSectionAtIndex(1); 1206 | loadaddr = sec.GetLoadAddress(target); 1207 | try: 1208 | f = open(command, "r"); 1209 | except: 1210 | output("Failed to load file : " + command); 1211 | result.PutCString("".join(GlobalListOutput)); 1212 | return; 1213 | while True: 1214 | line = f.readline(); 1215 | if not line: break; 1216 | line = line.rstrip(); 1217 | if not line: break; 1218 | debugger.HandleCommand("breakpoint set -a " + hex(loadaddr + long(line, 16))); 1219 | f.close(); 1220 | 1221 | 1222 | def LoadBreakPoints(debugger, command, result, dict): 1223 | global GlobalOutputList; 1224 | GlobalOutputList = []; 1225 | 1226 | try: 1227 | f = open(command, "r"); 1228 | except: 1229 | output("Failed to load file : " + command); 1230 | result.PutCString("".join(GlobalListOutput)); 1231 | return; 1232 | while True: 1233 | line = f.readline(); 1234 | if not line: 1235 | break; 1236 | line = line.rstrip(); 1237 | if not line: 1238 | break; 1239 | debugger.HandleCommand("breakpoint set --name " + line); 1240 | f.close(); 1241 | 1242 | ''' 1243 | si, c, r instruction override deault ones to consume their output. 1244 | For example: 1245 | si is thread step-in which by default dumps thread and frame info 1246 | after every step. Consuming output of this instruction allows us 1247 | to nicely display informations in our hook-stop 1248 | Same goes for c and r (continue and run) 1249 | ''' 1250 | def si(debugger, command, result, dict): 1251 | debugger.SetAsync(True); 1252 | res = lldb.SBCommandReturnObject(); 1253 | lldb.debugger.GetSelectedTarget().process.selected_thread.StepInstruction(False); 1254 | result.SetStatus(lldb.eReturnStatusSuccessFinishNoResult); 1255 | 1256 | def c(debugger, command, result, dict): 1257 | debugger.SetAsync(True); 1258 | res = lldb.SBCommandReturnObject(); 1259 | lldb.debugger.GetSelectedTarget().GetProcess().Continue(); 1260 | result.SetStatus(lldb.eReturnStatusSuccessFinishNoResult ); 1261 | 1262 | def r(debugger, command, result, dict): 1263 | debugger.SetAsync(True); 1264 | res = lldb.SBCommandReturnObject(); 1265 | if command[0:3] == "-c/": 1266 | index = command.find("--"); 1267 | command = command[index+2:]; 1268 | #strip -c/bin/sh or -c/bin/bash -- when arguments are passed to cmd line... 1269 | lldb.debugger.GetCommandInterpreter().HandleCommand("process launch -- " + command, res); 1270 | result.SetStatus(lldb.eReturnStatusSuccessFinishNoResult ); 1271 | 1272 | ''' 1273 | Handles 'u' command which displays instructions. Also handles output of 1274 | 'disassemble' command ... 1275 | ''' 1276 | def DumpInstructions(debugger, command, result, dict): 1277 | global GlobalListOutput; 1278 | global arm_type; 1279 | GlobalListOutput = []; 1280 | 1281 | if is_arm(): 1282 | cpsr = int(get_register("cpsr"), 16); 1283 | t = (cpsr >> 5) & 1; 1284 | if t: 1285 | #it's thumb 1286 | arm_type = "thumbv7-apple-ios"; 1287 | else: 1288 | arm_type = "armv7-apple-ios"; 1289 | res = lldb.SBCommandReturnObject(); 1290 | cmd = command.split(); 1291 | if len(cmd) == 0 or len(cmd) > 2: 1292 | if is_arm(): 1293 | lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble -A " +arm_type + " --start-address=$pc --count=8", res); 1294 | else: 1295 | lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble --start-address=$pc --count=8", res); 1296 | elif len(cmd) == 1: 1297 | if is_arm(): 1298 | lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble -A "+arm_type+" --start-address=" + cmd[0] + " --count=8", res); 1299 | else: 1300 | lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble --start-address=" + cmd[0] + " --count=8", res); 1301 | else: 1302 | if is_arm(): 1303 | lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble -A "+arm_type+" --start-address=" + cmd[0] + " --count="+cmd[1], res); 1304 | lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble --start-address=" + cmd[0] + " --count="+cmd[1], res); 1305 | 1306 | if res.Succeeded() == True: 1307 | output(res.GetOutput()); 1308 | else: 1309 | output("Error getting instructions for : " + command); 1310 | 1311 | result.PutCString("".join(GlobalListOutput)); 1312 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1313 | 1314 | ''' 1315 | Implements stepover instruction. Unfortunatelly here is no internal breakpoint exposed to Python 1316 | thus all breaks have to be visible. Internal breakpoints are breakpoints which are < 0 (eg. -1 etc...) 1317 | and their existance is visible from : 1318 | lldb/sources/Target/Target.cpp 1319 | 1320 | BreakpointSP 1321 | Target::CreateBreakpoint (const FileSpecList *containingModules, 1322 | const FileSpec &file, 1323 | uint32_t line_no, 1324 | LazyBool check_inlines, 1325 | LazyBool skip_prologue, 1326 | bool internal, 1327 | bool hardware) 1328 | 1329 | ''' 1330 | 1331 | bplist = []; 1332 | 1333 | def stepo(debugger, command, result, dict): 1334 | global GlobalListOutput; 1335 | global arm_type; 1336 | GlobalListOutput = []; 1337 | debugger.SetAsync(True); 1338 | arch = get_arch(); 1339 | 1340 | result.SetStatus(lldb.eReturnStatusSuccessFinishNoResult); 1341 | 1342 | err = lldb.SBError(); 1343 | target = lldb.debugger.GetSelectedTarget(); 1344 | 1345 | if is_arm(): 1346 | cpsr = int(get_register("cpsr"), 16); 1347 | t = (cpsr >> 5) & 1; 1348 | if t: 1349 | #it's thumb 1350 | arm_type = "thumbv7-apple-ios"; 1351 | else: 1352 | arm_type = "armv7-apple-ios"; 1353 | 1354 | res = lldb.SBCommandReturnObject(); 1355 | #if is_arm(): 1356 | # lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble -A " +arm_type + " --raw --start-address=$pc --count=2", res); 1357 | #else: 1358 | # lldb.debugger.GetCommandInterpreter().HandleCommand("disassemble --raw --start-address=$pc --count=2", res); 1359 | 1360 | lldb.debugger.GetCommandInterpreter().HandleCommand("x/2i $pc", res); 1361 | if res.Succeeded() != True: 1362 | output("[X] Error in stepo... can't disassemble at pc"); 1363 | return; 1364 | 1365 | #use regex to locate hex addrress which is between 8-16 1366 | #as lldb changes disassembly very often... sometimes is has -> 1367 | #sometimes doesn't, and instead of always looking for different 1368 | #pattern, just use regex... Matching hex is dropped to 4 digits 1369 | #because of x32 where it prints 4 digits... 1370 | stuff = res.GetOutput(); 1371 | stuff = stuff.splitlines(True); 1372 | newlst = []; 1373 | for x in stuff: 1374 | if x == "\n": continue; 1375 | newlst.append(x); 1376 | stuff = newlst; 1377 | 1378 | p = re.compile("0x[\da-fA-F]{1,16}"); 1379 | current_pc = p.search(stuff[0]).group(0); 1380 | next_pc = p.search(stuff[1]).group(0); 1381 | current_pc = long(current_pc, 16); 1382 | next_pc = long(next_pc, 16); 1383 | 1384 | pc_inst = stuff[0].split(";")[0]; 1385 | if is_arm(): 1386 | if "blx" in pc_inst or "bl " in pc_inst: 1387 | breakpoint = target.BreakpointCreateByAddress(next_pc); 1388 | breakpoint.SetThreadID(get_frame().GetThread().GetThreadID()); 1389 | breakpoint.SetOneShot(True); 1390 | breakpoint.SetThreadID(get_frame().GetThread().GetThreadID()); 1391 | target.GetProcess().Continue(); 1392 | #debugger.HandleCommand("c"); 1393 | #debugger.HandleCommand("thread step-inst-over"); 1394 | return; 1395 | else: 1396 | lldb.debugger.GetSelectedTarget().process.selected_thread.StepInstruction(False); 1397 | #debugger.HandleCommand("si"); 1398 | return; 1399 | if "call" in pc_inst or "movs" in pc_inst or "stos" in pc_inst or "loop" in pc_inst or "cmps" in pc_inst: 1400 | breakpoint = target.BreakpointCreateByAddress(next_pc); 1401 | breakpoint.SetOneShot(True); 1402 | breakpoint.SetThreadID(get_frame().GetThread().GetThreadID()); 1403 | target.GetProcess().Continue(); 1404 | else: 1405 | lldb.debugger.GetSelectedTarget().process.selected_thread.StepInstruction(False); 1406 | 1407 | def hexdump(addr, chars, sep, width ): 1408 | l = []; 1409 | while chars: 1410 | line = chars[:width] 1411 | chars = chars[width:] 1412 | line = line.ljust( width, '\000' ) 1413 | arch = get_arch(); 1414 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1415 | szaddr = "0x%.08X" % addr; 1416 | else: # is_x64(): 1417 | szaddr = "0x%.016lX" % addr; 1418 | l.append("\033[1m%s :\033[0m %s%s \033[1m%s\033[0m" % (szaddr, sep.join( "%02X" % ord(c) for c in line ), sep, quotechars( line ))); 1419 | addr += 0x10; 1420 | return "\n".join(l); 1421 | 1422 | def quotechars( chars ): 1423 | #return ''.join( ['.', c][c.isalnum()] for c in chars ) 1424 | data = ""; 1425 | for x in chars: 1426 | if isinstance(chars, bytes): 1427 | x = chr(x); 1428 | if ord(x) >= 0x20 and ord(x) <= 126: 1429 | data += x; 1430 | else: 1431 | data += "."; 1432 | return data; 1433 | 1434 | ''' 1435 | Output nice hexdump... Should be db (in the future) so we can give dw/dd/dq 1436 | outputs as it's done with any normal debugger... 1437 | ''' 1438 | def dd(debugger, command, result, dict): 1439 | global GlobalListOutput; 1440 | 1441 | GlobalListOutput = []; 1442 | 1443 | arch = get_arch(); 1444 | value = get_frame().EvaluateExpression(command); 1445 | if value.IsValid() == False: 1446 | output("Error evaluating expression : " + command); 1447 | result.PutCString("".join(GlobalListOutput)); 1448 | return; 1449 | try: 1450 | value = int(value.GetValue(), 10); 1451 | except: 1452 | output("Error evaluating expression : " + command); 1453 | result.PutCString("".join(GlobalListOutput)); 1454 | return; 1455 | 1456 | err = lldb.SBError(); 1457 | target = lldb.debugger.GetSelectedTarget(); 1458 | size = 0x100; 1459 | while size != 0: 1460 | membuff = target.GetProcess().ReadMemory(value, size, err); 1461 | if err.Success() == False and size == 0: 1462 | output(str(err)); 1463 | result.PutCString("".join(GlobalListOutput)); 1464 | return; 1465 | if err.Success() == True: 1466 | break; 1467 | size = size - 1; 1468 | membuff = membuff + b"\x00" * (0x100-size); 1469 | color(BLUE); 1470 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1471 | output("[0x0000:0x%.08X]" % value); 1472 | output("------------------------------------------------------"); 1473 | else: #is_x64(): 1474 | output("[0x0000:0x%.016lX]" % value); 1475 | output("------------------------------------------------------"); 1476 | color_bold(); 1477 | output("[data]") 1478 | color_reset(); 1479 | output("\n"); 1480 | #output(hexdump(value, membuff, " ", 16)); 1481 | index = 0; 1482 | while index < 0x100: 1483 | data = struct.unpack("B"*16, membuff[index:index+0x10]); 1484 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1485 | szaddr = "0x%.08X" % value; 1486 | else: #is_x64(): 1487 | szaddr = "0x%.016lX" % value; 1488 | fmtnice = "%.02X %.02X %.02X %.02X %.02X %.02X %.02X %.02X" 1489 | fmtnice = fmtnice + " - " + fmtnice; 1490 | output("\033[1m%s :\033[0m %.02X %.02X %.02X %.02X %.02X %.02X %.02X %.02X - %.02X %.02X %.02X %.02X %.02X %.02X %.02X %.02X \033[1m%s\033[0m" % 1491 | (szaddr, 1492 | data[0], 1493 | data[1], 1494 | data[2], 1495 | data[3], 1496 | data[4], 1497 | data[5], 1498 | data[6], 1499 | data[7], 1500 | data[8], 1501 | data[9], 1502 | data[10], 1503 | data[11], 1504 | data[12], 1505 | data[13], 1506 | data[14], 1507 | data[15], 1508 | quotechars(membuff[index:index+0x10]))); 1509 | if index + 0x10 != 0x100: 1510 | output("\n"); 1511 | index += 0x10; 1512 | value += 0x10; 1513 | color_reset(); 1514 | #last element of the list has all data output... 1515 | #so we remove last \n 1516 | result.PutCString("".join(GlobalListOutput)); 1517 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1518 | 1519 | def dq(debugger, command, result, dict): 1520 | global GlobalListOutput; 1521 | 1522 | GlobalListOutput = []; 1523 | 1524 | arch = get_arch(); 1525 | value = get_frame().EvaluateExpression(command); 1526 | if value.IsValid() == False: 1527 | output("Error evaluating expression : " + command); 1528 | result.PutCString("".join(GlobalListOutput)); 1529 | return; 1530 | try: 1531 | value = int(value.GetValue(), 10); 1532 | except: 1533 | output("Error evaluating expression : " + command); 1534 | result.PutCString("".join(GlobalListOutput)); 1535 | return; 1536 | 1537 | err = lldb.SBError(); 1538 | target = lldb.debugger.GetSelectedTarget(); 1539 | size = 0x100; 1540 | while size != 0: 1541 | membuff = target.GetProcess().ReadMemory(value, size, err); 1542 | if err.Success() == False and size == 0: 1543 | output(str(err)); 1544 | result.PutCString("".join(GlobalListOutput)); 1545 | return; 1546 | if err.Success() == True: 1547 | break; 1548 | size = size - 8; 1549 | membuff = membuff + b"\x00" * (0x100-size); 1550 | if err.Success() == False: 1551 | output(str(err)); 1552 | result.PutCString("".join(GlobalListOutput)); 1553 | return; 1554 | 1555 | color(BLUE); 1556 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1557 | output("[0x0000:0x%.08X]" % value); 1558 | output("-------------------------------------------------------"); 1559 | else: #is_x64(): 1560 | output("[0x0000:0x%.016lX]" % value); 1561 | output("-------------------------------------------------------"); 1562 | color_bold(); 1563 | output("[data]") 1564 | color_reset(); 1565 | output("\n"); 1566 | index = 0; 1567 | while index < 0x100: 1568 | (mem0, mem1, mem2, mem3) = struct.unpack("QQQQ", membuff[index:index+0x20]); 1569 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1570 | szaddr = "0x%.08X" % value; 1571 | else: #is_x64(): 1572 | szaddr = "0x%.016lX" % value; 1573 | output("\033[1m%s :\033[0m %.016lX %.016lX %.016lX %.016lX" % (szaddr, mem0, mem1, mem2, mem3)); 1574 | if index + 0x20 != 0x100: 1575 | output("\n"); 1576 | index += 0x20; 1577 | value += 0x20; 1578 | color_reset(); 1579 | result.PutCString("".join(GlobalListOutput)); 1580 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1581 | 1582 | def ddword(debugger, command, result, dict): 1583 | global GlobalListOutput; 1584 | 1585 | GlobalListOutput = []; 1586 | 1587 | arch = get_arch(); 1588 | value = get_frame().EvaluateExpression(command); 1589 | if value.IsValid() == False: 1590 | output("Error evaluating expression : " + command); 1591 | result.PutCString("".join(GlobalListOutput)); 1592 | return; 1593 | try: 1594 | value = int(value.GetValue(), 10); 1595 | except: 1596 | output("Error evaluating expression : " + command); 1597 | result.PutCString("".join(GlobalListOutput)); 1598 | return; 1599 | 1600 | err = lldb.SBError(); 1601 | target = lldb.debugger.GetSelectedTarget(); 1602 | size = 0x100; 1603 | while size != 0: 1604 | membuff = target.GetProcess().ReadMemory(value, size, err); 1605 | if err.Success() == False and size == 0: 1606 | output(str(err)); 1607 | result.PutCString("".join(GlobalListOutput)); 1608 | return; 1609 | if err.Success() == True: 1610 | break; 1611 | size = size - 4; 1612 | membuff = membuff + b"\x00" * (0x100-size); 1613 | color(BLUE); 1614 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1615 | output("[0x0000:0x%.08X]" % value); 1616 | output("----------------------------------------"); 1617 | else: #is_x64(): 1618 | output("[0x0000:0x%.016lX]" % value); 1619 | output("----------------------------------------"); 1620 | color_bold(); 1621 | output("[data]") 1622 | color_reset(); 1623 | output("\n"); 1624 | index = 0; 1625 | while index < 0x100: 1626 | (mem0, mem1, mem2, mem3) = struct.unpack("IIII", membuff[index:index+0x10]); 1627 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1628 | szaddr = "0x%.08X" % value; 1629 | else: #is_x64(): 1630 | szaddr = "0x%.016lX" % value; 1631 | output("\033[1m%s :\033[0m %.08X %.08X %.08X %.08X \033[1m%s\033[0m" % (szaddr, 1632 | mem0, 1633 | mem1, 1634 | mem2, 1635 | mem3, 1636 | quotechars(membuff[index:index+0x10]))); 1637 | if index + 0x10 != 0x100: 1638 | output("\n"); 1639 | index += 0x10; 1640 | value += 0x10; 1641 | color_reset(); 1642 | result.PutCString("".join(GlobalListOutput)); 1643 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1644 | 1645 | def dw(debugger, command, result, dict): 1646 | global GlobalListOutput; 1647 | 1648 | GlobalListOutput = []; 1649 | 1650 | arch = get_arch(); 1651 | value = get_frame().EvaluateExpression(command); 1652 | if value.IsValid() == False: 1653 | output("Error evaluating expression : " + command); 1654 | result.PutCString("".join(GlobalListOutput)); 1655 | return; 1656 | try: 1657 | value = int(value.GetValue(), 10); 1658 | except: 1659 | output("Error evaluating expression : " + command); 1660 | result.PutCString("".join(GlobalListOutput)); 1661 | return; 1662 | 1663 | err = lldb.SBError(); 1664 | target = lldb.debugger.GetSelectedTarget(); 1665 | size = 0x100; 1666 | while size != 0: 1667 | membuff = target.GetProcess().ReadMemory(value, size, err); 1668 | if err.Success() == False and size == 0: 1669 | output(str(err)); 1670 | result.PutCString("".join(GlobalListOutput)); 1671 | return; 1672 | if err.Success() == True: 1673 | break; 1674 | size = size - 2; 1675 | membuff = membuff + b"\x00" * (0x100-size); 1676 | 1677 | color(BLUE); 1678 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1679 | output("[0x0000:0x%.08X]" % value); 1680 | output("--------------------------------------------"); 1681 | else: #is_x64(): 1682 | output("[0x0000:0x%.016lX]" % value); 1683 | output("--------------------------------------------"); 1684 | color_bold(); 1685 | output("[data]") 1686 | color_reset(); 1687 | output("\n"); 1688 | index = 0; 1689 | while index < 0x100: 1690 | data = struct.unpack("HHHHHHHH", membuff[index:index+0x10]); 1691 | if get_pointer_size() == 4: #is_i386() or is_arm(): 1692 | szaddr = "0x%.08X" % value; 1693 | else: #is_x64(): 1694 | szaddr = "0x%.016lX" % value; 1695 | output("\033[1m%s :\033[0m %.04X %.04X %.04X %.04X %.04X %.04X %.04X %.04X \033[1m%s\033[0m" % (szaddr, 1696 | data[0], 1697 | data[1], 1698 | data[2], 1699 | data[3], 1700 | data[4], 1701 | data[5], 1702 | data[6], 1703 | data[7], 1704 | quotechars(membuff[index:index+0x10]))); 1705 | if index + 0x10 != 0x100: 1706 | output("\n"); 1707 | index += 0x10; 1708 | value += 0x10; 1709 | color_reset(); 1710 | result.PutCString("".join(GlobalListOutput)); 1711 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1712 | 1713 | def IphoneConnect(debugger, command, result, dict): 1714 | global GlobalListOutput; 1715 | GlobalListOutput = []; 1716 | 1717 | if len(command) == 0 or ":" not in command: 1718 | output("Connect to remote iPhone debug server"); 1719 | output("\n"); 1720 | output("iphone "); 1721 | output("\n"); 1722 | output("iphone 192.168.0.2:5555"); 1723 | result.PutCString("".join(GlobalListOutput)); 1724 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1725 | return; 1726 | 1727 | res = lldb.SBCommandReturnObject(); 1728 | lldb.debugger.GetCommandInterpreter().HandleCommand("platform select remote-ios", res); 1729 | if res.Succeeded() == True: 1730 | output(res.GetOutput()); 1731 | else: 1732 | output("Error running platform select remote-ios"); 1733 | result.PutCString("".join(GlobalListOutput)); 1734 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1735 | return; 1736 | lldb.debugger.GetCommandInterpreter().HandleCommand("process connect connect://" + command, res); 1737 | if res.Succeeded() == True: 1738 | output("Connected to iphone at : " + command); 1739 | else: 1740 | output(res.GetOutput()); 1741 | result.PutCString("".join(GlobalListOutput)); 1742 | result.SetStatus(lldb.eReturnStatusSuccessFinishResult); 1743 | 1744 | def findmem(debugger, command, result, dict): 1745 | global GlobalListOutput; 1746 | GlobalListOutput = []; 1747 | 1748 | arg = str(command); 1749 | parser = argparse.ArgumentParser(prog="lldb"); 1750 | parser.add_argument("-s", "--string", help="Search string"); 1751 | parser.add_argument("-u", "--unicode", help="Search unicode string"); 1752 | parser.add_argument("-b", "--binary", help="Serach binary string"); 1753 | parser.add_argument("-d", "--dword", help="Find dword (native packing)"); 1754 | parser.add_argument("-q", "--qword", help="Find qword (native packing)"); 1755 | parser.add_argument("-f", "--file" , help="Load find pattern from file"); 1756 | parser.add_argument("-c", "--count", help="How many occurances to find, default is all"); 1757 | 1758 | parser = parser.parse_args(arg.split()); 1759 | 1760 | if parser.string != None: 1761 | search_string = parser.string.encode(); #parser.string; 1762 | elif parser.unicode != None: 1763 | search_string = parser.unicode.encode("utf-16-le"); #unicode(parser.unicode); 1764 | elif parser.binary != None: 1765 | search_string = bytes.fromhex(parser.binary); #parser.binary.decode("hex"); 1766 | elif parser.dword != None: 1767 | dword = evaluate(parser.dword); 1768 | if dword == None: 1769 | print("Error evaluating : " + parser.dword); 1770 | return; 1771 | search_string = struct.pack("I", dword & 0xffffffff); 1772 | elif parser.qword != None: 1773 | qword = evaluate(parser.qword); 1774 | if qword == None: 1775 | print("Error evaluating : " + parser.qword); 1776 | return; 1777 | search_string = struct.pack("Q", qword & 0xffffffffffffffff); 1778 | elif parser.file != None: 1779 | f = 0; 1780 | try: 1781 | f = open(parser.file, "rb"); 1782 | except: 1783 | print("Failed to open file : " + parser.file); 1784 | return; 1785 | search_string = f.read(); 1786 | f.close(); 1787 | else: 1788 | print("Wrong option... use findmem --help"); 1789 | return; 1790 | 1791 | count = -1; 1792 | if parser.count != None: 1793 | count = evaluate(parser.count); 1794 | if count == None: 1795 | print("Error evaluating count : " + parser.count); 1796 | return; 1797 | 1798 | process = lldb.debugger.GetSelectedTarget().GetProcess(); 1799 | pid = process.GetProcessID(); 1800 | output_data = subprocess.check_output(["/usr/bin/vmmap", "%d" % pid]) 1801 | if isinstance(output_data, bytes): 1802 | output_data = output_data.decode(); 1803 | lines = output_data.split("\n"); 1804 | #print(lines); 1805 | #this relies on output from /usr/bin/vmmap so code is dependant on that 1806 | #only reason why it's used is for better description of regions, which is 1807 | #nice to have. If they change vmmap in the future, I'll use my version 1808 | #and that output is much easier to parse... 1809 | newlines = []; 1810 | for x in lines: 1811 | p = re.compile("([\S\s]+)\s([\da-fA-F]{16}-[\da-fA-F]{16}|[\da-fA-F]{8}-[\da-fA-F]{8})"); 1812 | m = p.search(x); 1813 | if not m: continue; 1814 | tmp = []; 1815 | mem_name = m.group(1); 1816 | mem_range = m.group(2); 1817 | mem_start = int(mem_range.split("-")[0], 16);# long(mem_range.split("-")[0], 16); #0x000000-0x000000 1818 | mem_end = int(mem_range.split("-")[1], 16);# long(mem_range.split("-")[1], 16); 1819 | tmp.append(mem_name); 1820 | tmp.append(mem_start); 1821 | tmp.append(mem_end); 1822 | newlines.append(tmp); 1823 | 1824 | lines = sorted(newlines, key=lambda sortnewlines: sortnewlines[1]); 1825 | #move line extraction a bit up, thus we can latter sort it, as vmmap gives 1826 | #readable pages only, and then writable pages, so it looks ugly a bit :) 1827 | newlines = []; 1828 | for x in lines: 1829 | mem_name = x[0]; 1830 | mem_start= x[1]; 1831 | mem_end = x[2]; 1832 | mem_size = mem_end - mem_start; 1833 | 1834 | err = lldb.SBError(); 1835 | 1836 | membuff = process.ReadMemory(mem_start, mem_size, err); 1837 | if err.Success() == False: 1838 | #output(str(err)); 1839 | #result.PutCString("".join(GlobalListOutput)); 1840 | continue; 1841 | off = 0; 1842 | base_displayed = 0; 1843 | 1844 | while True: 1845 | if count == 0: return; 1846 | idx = membuff.find(search_string); 1847 | if idx == -1: break; 1848 | if count != -1: 1849 | count = count - 1; 1850 | off += idx; 1851 | 1852 | GlobalListOutput = []; 1853 | 1854 | if get_pointer_size() == 4: 1855 | ptrformat = "%.08X"; 1856 | else: 1857 | ptrformat = "%.016lX"; 1858 | 1859 | color_reset(); 1860 | output("Found at : "); 1861 | color(GREEN); 1862 | output(ptrformat % (mem_start + off)); 1863 | color_reset(); 1864 | if base_displayed == 0: 1865 | output(" base : "); 1866 | color(YELLOW); 1867 | output(ptrformat % mem_start); 1868 | color_reset(); 1869 | base_displayed = 1; 1870 | else: 1871 | output(" "); 1872 | if get_pointer_size() == 4: 1873 | output(" " * 8); 1874 | else: 1875 | output(" " * 16); 1876 | #well if somebody allocated 4GB of course offset will be to small to fit here 1877 | #but who cares... 1878 | output(" off : %.08X %s" % (off, mem_name)); 1879 | print("".join(GlobalListOutput)); 1880 | membuff = membuff[idx+len(search_string):]; 1881 | off += len(search_string); 1882 | return; 1883 | --------------------------------------------------------------------------------