Search code examples
macosdebuggingnsstringreverse-engineeringlldb

Setting a register value to NSString in lldb


I'm trying to change a register value from one NSString to another, when I look at the registers - in this example "rdx" is pointing to an NSString object:

(lldb) register read
General Purpose Registers:
       rax = 0x0000000000000000
       rbx = 0x0000000000000000
       rcx = 0x0000000000007d0b
       rdx = 0x00007fffb6e40860  @"Helvetica"

Now I tried to change it's value in multiple ways - I tried to create an NSString object in "expression" and set it to $rdx:

(lldb) expression
Enter expressions, then terminate with an empty line to evaluate:
  1: NSString *abc=@"Times"; 
  2: $rdx=abc;
error: assigning to 'unsigned long' from incompatible type 'NSString *'

Now I remembered rdx is only a pointer to an NSString object, so I tried to get the pointer value (unsigned long) and set it to rdx:

(lldb) expression
Enter expressions, then terminate with an empty line to evaluate:
  1: NSString *abc=@"Times"; 
  2: $rdx=(unsigned long)&abc; 
(unsigned long) $110 = 123145406123008

Now register read shows only a pointer value instead of an NSString value

(lldb) register read 
General Purpose Registers:
       rax = 0x0000000000000000
       rbx = 0x0000000000000000
       rcx = 0x0000000000007d0b
       rdx = 0x000070000e275d00

When I let the program continue - it crashes...

Now I know that I'm missing something, since the initial value of rdx pointing to the NSString (0x00007fffb6e40860) - when reading it from memory it points to another pointer (7fffb3d721b8, which points to junk data...)

(lldb) memory read 0x00007fffb6e40860
0x7fffb6e40860: b8 21 d7 b3 ff 7f 00 00 c8 07 00 00 00 00 00 00  ?!׳?...?.......

And when reading the value after assigning rdx to my NSString pointer - it does show the string value:

(lldb) memory read 0x000070000f8a3d00
0x70000f8a3d00: 55 54 69 6d 65 73 00 00 00 00 00 00 00 00 00 00  UTimes..........

If it wasn't clear enough - my goal is to set rdx so it would show something like this:

(lldb) register read
General Purpose Registers:
       rax = 0x0000000000000000
       rbx = 0x0000000000000000
       rcx = 0x0000000000007d0b
       rdx = 0x00007fffb6e40860  @"Times"

Solution

  • You've got 2 options:

    Create the string, get the reference to it, then set it using register write

    (lldb) p/x @"hello world"
    (__NSCFString *) $0 = 0x00006000002232a0 @"hello world"
    (lldb) register write rdx 0x00006000002232a0
    (lldb) p/x $rdx
    (unsigned long) $1 = 0x00006000002232a0
    (lldb) po $rdx 
    hello world
    

    Alternatively, you can use the expression command as well:

    (lldb) p/x @"goodbye world"
    (__NSCFString *) $1 = 0x0000604000423000 @"goodbye world"
    (lldb) po $rdx = 0x0000600000223220
    goodbye world
    
    (lldb) po $rdx
    goodbye world