I need to find how to get the value to make a branch between two points in IDA Pro, but I can’t figure it out. For more context: the instructions I’m following says “Calculate the value needed to do a branch from 176E4 to 1768C, which will be D2 E7”. How do they get D2 E7 from 176E4 and 1768C? Is there a math formula or is there somewhere in IDA where they find this? It's arm little endian. Thank you
-
who's "they"? also, which ARM?– Igor Skochinsky ♦Aug 27, 2021 at 14:19
-
“They” is whoever wrote the guide I referenced, and it’s arm little endian.– t0astym4rshAug 27, 2021 at 18:57
-
got a link to the guide?– Igor Skochinsky ♦Aug 27, 2021 at 19:17
-
theiphonewiki.com/wiki/Tutorial:Odysseus_Bundles#ASR_Patch Yes. The part I’m referencing is under asr patch– t0astym4rshAug 27, 2021 at 22:59
2 Answers
This is an unconditional branch (thumb)
It is encoded as 11100
|signed 11-bit immediate offset
E 7 D 2
1110 0111 1101 0010
so your 11-bit offset is 0b11111010010. This is sign extended to -46
The operation is:
PC = PC + (SignExtend(signed_immed_11) << 1)
where the first PC contains the address of the branch plus 4.
0x176E4 + 4 + (-46 * 2) == 0x1768C
-
-
this is basic algebra at this point
SRC + 4 + (X * 2) == DEST
solve for X.(0x1768C - 0x176E4 - 4) / 2
is a signed 11-bit number prepended by11100
– mumbelAug 28, 2021 at 0:08
PC = current Instruction pointer + instruction length
PC = IP + 4
PC = 0x176E4 + 4 == 176E8
destination = 0x1768C
offset is encoded as a signed number of ((destination - PC)>>1)
:\>python -c "print(hex((0x1768c-0x176e8)>>1))
-0x2e
unconditional jump B can be encoded from E0 00 to E7 FF ==> E + (0x0 to 0x7ff ) == 0b1110 + (0b00000000000 .. 0b11111111111
E0 00 to E3 FF ARE FORWARD JUMPS FROM PC
E4 00 TO E7 FF ARE BACKWARD JUMPS FROM PC
-0X2E IS A BACKWARD JUMP
SO SUBTRACT 0X2E FROM 0X800 TO GET 0X7D2
using capstone and python
import capstone
cs = capstone.Cs(capstone.CS_ARCH_ARM , capstone.CS_MODE_THUMB)
cs.Detail = True
inp = [b'\x00\xe0',b'\x01\xe0',b'\x02\xe0',b'\xff\xe3',b'\x00\xe4',b'\xff\xe7',b'\xd2\xe7']
for j in range(0,len(inp),1):
dis = cs.disasm( inp[j], 0x176e4)
for i in dis:
print(i.bytes ,("0x%x:\t" % i.address),("%s %s" %(i.mnemonic, i.op_str)))
executed
:\>python arm.py
bytearray(b'\x00\xe0') 0x176e4: b #0x176e8
bytearray(b'\x01\xe0') 0x176e4: b #0x176ea
bytearray(b'\x02\xe0') 0x176e4: b #0x176ec
bytearray(b'\xff\xe3') 0x176e4: b #0x17ee6
bytearray(b'\x00\xe4') 0x176e4: b #0x16ee8
bytearray(b'\xff\xe7') 0x176e4: b #0x176e6
bytearray(b'\xd2\xe7') 0x176e4: b #0x1768c <<<<<<<<<<