下面內容涵蓋硬patch時會使用的技巧:算法
1、修改函數中調用的字符串變量c#
一、在data段找個位置存放字符串以\00結尾,記下地址A函數
二、找到函數中的 spa
09 48 LDR R0, =(aDataLocalTmpTe - 0xD62) ,記下地址Bcode
. 78 44 ADD R0, PC ;記下地址C字符串
LDR R0, =(aDataLocalTmpTe - 0xD62) 等於 LDR R0,[pc, #100],也就是說aDataLocalTmpTe - 0xD62計算的這個偏移存放在當前pc+100處的位置,記地址D,此時pc+100處的數據如:get
text:0000F168 9C 6D 00 00 off_F168 DCD aDataLocalTmpTe - 0xF14A
道先計算字符串離當前PC的位置存放到當前函數下面的數據偏移裏,
io
一、字符串到調用PC :偏移A=地址A-地址C-4class
二、偏移A存放到函數尾部的F168處pdf
三、計算地址B處的Opcode,詳情查看thumb指令的LDR opcode格式(https://ece.uwaterloo.ca/~ece222/ARM/ARM7-TDMI-manual-pt3.pdf),
48主要是操做哪一個寄存器,偏移主要是09這個字節,這個偏移的計算方法是:
(地址D-地址B-2)/4=opcode
2、函數調用相關
指令action: B <Target Addr> PC = PC + (#OFF << 1)
指令opcode: B <Target Addr> 1 1 1 0 0 #Offset[0-10] ;其中15個字節中的0-10位爲偏移
0000F0F8 01 E0 B locret_F0FE ;F0FE-F0F8=#6
E001對應的二進制爲 11100 00000000001,也就是偏移爲1使用action計算以下,pc=pc+1<<1=pc+2,此處注意pc會自動加4,也就是pc+2=4+2=6,恰好等於B #6
1.向後跳轉
0012 00F001F8 bl .Lhelo
.Lhelo:
0018 05F0D1F7 pld [r1, r5]
計算方式:
取高位 f000, 取後11位 => 000
取低位 f801, 取後11位 => 001
計算: (000 << 12) | (001 << 1) = 2
因爲這個最高位符號位爲0. 表明向後跳轉, 只須要保留該值2便可
而後計算獲得的目標地址爲 : 0x0012 + 4 + 2 = 0x0018
向前跳轉
00001164 FF F7 BE FF BL _Z4testv
_Z4testv
000010E4 07 B5 PUSH {R0-R2,LR}
計算方式:
取高位 f7ff, 取後11位 => 7ff
取低位 ffbe, 取後11位 => 7be
計算: (7ff << 12) | (7be << 1) = 7fff7c
因爲這個最高位符號位爲1 表明向前跳轉, 須要-1而後取反 獲得值爲 ff800084。取84便可
而後算獲得的目標地址爲 : 0x1164 + 4 - 0x84 = 0x10e4
逆向過程:
BL <label>
由BL指令獲得機器碼算法:
offset = dstAddr - srcAddr; offset = (offset -4) & 0x007ffffff high = offset >> 12; low = (offset & 0x00000fff) >> 1; machineCode = ((0xFF00 | low) << 16) | (0xF000 | high);
BLX <label>
與BL相似。
offset = dstAddr - srcAddr; offset = (offset -4) & 0x007fffff; high = offset >> 12; low = (offset & 0x00000fff) >> 1; if(low%2 != 0) { low++; } machineCode = ((0xEF00 | low) << 16) | (0xF000 | high);