3

I am trying to patch a cydia tweak which has been developed by using Objective-C. I would like to modify a piece of code to suite my need.

I'm using IDA Pro V6.8 for my examining. After inspecting, I recognize that each Hex byte would represent a part of an assembly line code.

Bellow is a screenshot for the code that I need to change. enter image description here

Looking at the above screenshot, we need to have 8 bytes (4A F2 A6 50 C0 F2 01 00) to represent a "MOV" instruction. Let's me say something about these 8 bytes:

  1. As I know, the first four bytes (4A F2 A6 50) represent for "#(cfstr_UnknownCallbac - 0x9F56)" which you see in the screenshot.
  2. The two following bytes (C0 F2) represent for an MOV instruction.
  3. The last two bytes (01 00) would tell the system to move value from the string into the register, in this case, the register is R0.

I have some concerns about the MOV instruction and the first four HEX bytes (4A F2 A6 50)

  1. What does the "0x9F56" in the instruction means?

  2. How does the system know that the first four bytes reflect correctly to "#(cfstr_UnknownCallbac - 0x9F56)" not any other string variables?

  3. I need to create a new string and then I will use it to replace the existing "#(cfstr_UnknownCallbac - 0x9F56)". I believe that I just need to replace the first four HEX bytes so that it would point to the new string, but I don't know what are the HEX codes should I have here.

Any help is appreciated, thank you very much.

2
  • Isn't it easier to just overwrite the previous string where that string actually is? Commented Aug 3, 2016 at 16:52
  • I would like to have a new string something like "There is an error when processing your request."
    – Josh
    Commented Aug 4, 2016 at 0:12

1 Answer 1

4

To understand what's happening, you need to learn about Position Independent Code (PIC).

In a nutshell, the compiler wants the executable code to be correct independent of where in memory it gets loaded. In the case of a shared library, the OS may load it at a different place every time; even if statically linked, PIC will make the linker's life easier.

The "trick" that's normally used on ARM processors to produce PIC is using PC (Program Counter) relative addresses. The compiler doesn't produce code that says "the string is at address 0x123456", it produces "the string is 0x1234 bytes behind this instruction". Thus, when the program is moved in memory, the "0x1234" stays the same.

Which is why your 2nd instruction adds the program counter to the relative address in R0.

Now, to know what ADD R0, PC really does, you need to know how the processor works. The processor is in Thumb (2 byte instructions) mode as you can see from the 2 bytes difference between 9F52 and 9F54, and when the processor executes the ADD R0, PC instruction, the prefetch unit will already have read the first two bytes of BLX _MSlog. So the PC that gets added is actually 9F56. This should answer your first question: in the display of the opcode's meaning, IDA subtracts the value it knows to be added in the next instruction.

Second question: I don't know the internals of IDA, but I'm 99% sure it looks for ADD Rx, PC instructions, and produces a string reference like yours at the preceding instruction that loads Rx, just because it knows this is the standard way of achieving PIC on ARM.

Third question: Manually disasembling Thumb is hard - really hard - as you can see if you check the Thumb instruction set. And no, 4a f2 a6 50 isn't just a data offset; it loads the lower 16 bits of the value, and C0 F2 01 00 loads the higher 16 bits of the value. The Online Disassembler translates those two sets of 4 byte instructions to

movw r0, #42406 ; 0xa5a6          
movt r0, #1

and you can read here about the movw and movt instructions. IDA is friendly enough to show all of this as one single 8-byte instruction, but under the hood, a lot more is going on.

So if you really want to change an offset like this, get familiar with the thumb manual I linked above, learn each and every bit, and assemble the new instructions manually. Or, just (ab)use the gnu assembler in the way I outlined in my answer to this question. Just write a bare minimum assembler snippet and have as handle the gory details for you.

But, as @joxeankoret said: if you just want to change a string, and don't need the original string anwhere else, and the new string isn't longer than the old one, overwriting the string with the new one will be much easier than finding a place for your new string and adjusting the offsets. You can jump to that position by double clicking the label in IDA, or just scroll to the address 2FF4C (1A5A6+9F56).

1
  • 1
    Much appreciate your very detailed answer. PIC and the thumb are quite new for me. I am going to look at these terms right away. Hopefully I will figure out the solution soon. Have a nice day!
    – Josh
    Commented Aug 4, 2016 at 1:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.