http://versprite.com/og/ios-reverse-engineering-part-two-debugging-and-tracing-with-lldb/
IOS Reverse Engineering Part two:debugging and tracing with Lldboverview
In our previous post–http://versprite.com/og/ios-reverse-engineering-part-one-configuring-lldb/–we learned what to con Figure and Setup Debugserver and lldb on your IOS device. In this post we'll demonstrate how to use LLDB to perform basic debugging and message tracing.
Objc_msgsend ()
This topic have already been covered numerous times, but lets run through a refresher on objective-c ' s objc_msgsend (). This function was one of the more important items within the LIBOBJC. A.dylib Library. During Runtime Objc_msgsend () is used to send messages to an object within memory. This can is considered the equivalent to calling functions in C.
The compiler would convert a message expression–[receiver message] into a call on Objc_msgsend (). When we take a look at the Objc_msgsend () declaration:
ID objc_msgsend (ID self, SEL op, arg1, arg2 ...)
We see as parameters it takes a pointer to the instance of the class which is to receive the message, and the selector of T He method that handles the message. Objc_msgsend () takes the ID type, which is literally just a pointer to a C struct, being identified as Objc_object. After a object is created, memory was allocated for the Objc_object type that consists if a ISA pointer, which is Followe D by the data for that object. In this usage, the ID of type is basically a pointer to the receiver's class instance in memory.
The second argument SEL, is pretty much the method ' s signature string representation. whew! Hopefully this was making a bit of sense, and now we can move to learning about ARM, and the Procedure The ARM Architecture.
ARM Calling conventions
The ARM architecture contains registers numbered R0–R15, each 32-bits wide. The procedure call standard state, the first four registers (R0–R3) is used to pass argument values into a Subrouti NE and to return a result value from a function.
The Prolog for a function call goes something like this:
–push the value of the link register (LR) (R14) to the stack
–push the value of the frame pointer (R7) to the stack
–update the frame pointer to the value of the stack pointer (SP)
–push the preserved registers to the stack
–make Space for local storage
A example might look like this:
Push {R4-R7, LR}//Save LR, R7, R4-r6add R7, SP, #12//adjust R7 to point to saved R7push {r8, R10, R11}// Save remaining GPRs (R8, R10, R11) Vstmdb sp!, {d8-d15}//Save vfp/advanced SIMD Registers d8sub sp, SP, #36//AL Locate space for local storage
Objc_msgsend () Tracing
In order to start tracing objc_msgsend (), let us combine everything we had learned so far. We know from the declaration that Objc_msgsend () takes-parameters, which point to the class instance and method Signat Ure. We also know from the ARM calling conventions, that the registers r0, and R1 would probably contain those respective values Being passed into the objc_msgsend () function.
We'll be using the Damn vulnerable IOS App for demonstration. The first thing I am going to do are set breakpoint at [INSECUREDATASTORAGEVULNVC saveinplistfiletapped:], because I only really wanna to trace the Objc_msgsend () calls within this subroutine.
(LLDB) b-[INSECUREDATASTORAGEVULNVC saveinplistfiletapped:] Breakpoint 1:where = Damnvulnerableiosapp '-[ INSECUREDATASTORAGEVULNVC saveinplistfiletapped:], address = 0x000e5c2c
Now when we venture-the application and attempt to save our data in the Plist file:
* Thread #1: tid = 0x145aa, 0x000d0c2c damnvulnerableiosapp '-[INSECUREDATASTORAGEVULNVC saveinplistfiletapped:], queue = ' Com.apple.main-thread ', stop reason = Breakpoint 1.1 frame #0:0x000d0c2c damnvulnerableiosapp '-[ INSECUREDATASTORAGEVULNVC Saveinplistfiletapped:]damnvulnerableiosapp '-[INSECUREDATASTORAGEVULNVC Saveinplistfiletapped:]:-> 0xd0c2c: push {r4, R5, R6, R7, LR} 0xd0c2e: add R7, SP, #0xc 0XD0C30: push.w {r8, R10, R11} 0xd0c34: Sub sp, #0xc
To start tracing the objc_msgsend () calls within this subroutine let us disassemble where we are currently located.
(lldb) Didamnvulnerableiosapp '-[INSECUREDATASTORAGEVULNVC saveinplistfiletapped:]:-> 0xd0c2c: push {R4 , R5, R6, R7, LR} 0xd0c2e: add R7, SP, #0xc 0xd0c30: push.w {r8, R10, R11} 0xd0c34: Sub sp, #0xc 0xd0c36: mov r4, r0 0xd0c38: movs r0, #0x9 0xd0c3a: movs R1, #0x1 0xd0c3c: movs R2, #0x1 0xd0c3e: blx 0x291db0 ; symbol stub for: Nssearchpathfordirectoriesindomains 0xd0c42: mov R7, R7 0xd0c44: blx 0x291e44 ; symbol stub for:objc_retainautoreleasedreturnvalue 0xd0c48: str r0, [sp, #0x8] 0xd0c4a: MOVW R1, #0x76b8 0xd0c4e: movt R1, #0x1d 0xd0c52: movs R2, #0x0 0XD0C54: add r1, PC 0xd0c56: ldr R1, [R1] 0xd0c58: blx 0x291e28 ; Symbol stub for:objc_msgsend 0xd0c5c: mov R7, R7
We can set a breakpoint at the address 0x291e28 for the objc_msgsend ().
(LLDB) b 0x291e28breakpoint 2:where = Damnvulnerableiosapp ' symbol stub for:objc_msgsend, address = 0x00291e28
However once we hit this breakpoint, we need to perform additional inspection. We can do this by adding a stop-hook:
(LLDB) Target Stop-hook addenter your stop hook command (s). Type ' done ' to end.> register read > x/s $r 1 > Expr-o--$r 0 > Donestop Hook #1 added.
Through This stoop-hook we'll read the values in the current registers, examine the contents of R1 as a string, and Prin T the object description of the pointer located in R0. Remember R1 should contain the selector and R0 should contain the class instance.
After resuming execution, we are hit the next breakpoint, which we have set, and our Stoop-hook is invoked.
General Purpose Registers: r0 = 0x176f6d70 r1 = 0x335c9122 "Objectatindex:" r2 = 0x00000000 R3 = 0x00000000 r4 = 0x176d50d0 R5 = 0X001402BF "saveinplistfiletapped:" r6 = 0x175d8d30 R7 = 0x27d40528 r8 = 0x17664620 R9 = 0x00000000 R10 = 0x175f1180 R11 = 0x00000000 R12 = 0x3d47f1d0< c15/> (void *) 0x3b627959: _OS_LOCK_HANDOFF_UNLOCK$VARIANT$MP + 1 sp = 0x27d40504 lr = 0x000d0c5d Damnvulnerableiosapp '-[INSECUREDATASTORAGEVULNVC saveinplistfiletapped:] + pc = 0x00291e28 Damnvulnerableiosapp ' symbol stub for:objc_msgsend CPSR = 0x400000100x335c9122: "Objectatindex:" <__nsarrayi 0x176f6d70> (/var/mobile/applications/04a94c51-51cd-4633-9649-ace1bccfed72/documents)
Everything looks to is working, now we have a little homemade tracer, and can start moving through the rest of the calls.
General Purpose Registers: r0 = 0x3b7b8df4 (void *) 0x3b7b8dcc:nsmutabledictionary r1 = 0x380953cd " Alloc " r2 = 0x002aa198 (void *) 0x3b7b8df4:nsmutabledictionary r3 = 0x00000001 R4 = 0x176d50d0 R5 = 0X001402BF "saveinplistfiletapped:" r6 = 0x175d8d30 R7 = 0x27d40528 r8 = 0x17664620 R9 = 0x17902868 R10 = 0x175f1180 R11 = 0x00000000 R12 = 0x3b011479 LIBOBJC. A.dylib '-[nsobject autorelease] + 1 sp = 0x27d40504 lr = 0x000d0ca3 damnvulnerableiosapp '-[ INSECUREDATASTORAGEVULNVC saveinplistfiletapped:] + 119 pc = 0x00291e28 Damnvulnerableiosapp ' symbol stub For:objc_msgsend CPSR = 0x600000100x380953cd: "Alloc" nsmutabledictionary
https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/gdb_to_lldb_transition_guide/document/ Lldb-command-examples.html
Reprint a debug article