一、目标
我们已经拿AndroidNativeEmu模拟执行出了sign的值,但是这个值对不对,除了直接往服务器发送之后,最好是能和真机算出来的对比验算下,这样才好放心它有没有做别的小动作。
二、分析
算法还原的助手(一) 先让时间停下来 的文章里面我们已经把联手机签名的结果固定下来了,所以在AndroidNativeEmu里面我们也需要Hook gettimeofday和lrand48。
从IDA的分析中可以看到,调用gettimeofday函数的时候 tv 的指针在R5寄存器中,所以我们只需要在函数返回之后的 0x129C0 地址上断下来,然后把R5地址所指向的内存值改成我们需要的定值就行了。
lrand48就比较简单了,函数的返回值一般都是存在R0寄存器里,我们只需要在函数返回的时候,在 0x00012A72 和 0x00012A8C 把R0写成我们需要的定值就行了。
def hook_code(mu, address, size, user_data):
global lib_moduleBase
try:
emu = user_data
if (not emu.memory.check_addr(address, UC_PROT_EXEC)):
logger.error("addr 0x%08X out of range"%(address,))
sys.exit(-1)
# 修改gettimeofday返回值
if (lib_moduleBase + 0x129C0) == address:
# 读取R5寄存器的值
r5 = mu.reg_read(UC_ARM_REG_R5)
logger.info(">>> addr 0x%08X,r5=0x%08X" %(address,r5))
# 读取R5指向的内存地址的值,就是tv的值
b = mu.mem_read(r5, 8).hex().upper()
logger.info(b)
# 给 tv写入一个定值
mu.mem_write(r5,b"\x91\x50\xc4\x5f\x15\x97\x09\x00")
# 看一眼,是不是写对了
b = mu.mem_read(r5, 8).hex().upper()
logger.info(b)
# 修改 lrand48的返回值
if (lib_moduleBase + 0x00012A72) == address or (lib_moduleBase + 0x00012A8C) == address :
r0 = mu.reg_read(UC_ARM_REG_R0)
logger.info(">>> addr 0x%08X,r0=0x%08X" %(address,r0))
mu.reg_write(UC_ARM_REG_R0,1)
except Exception as e:
logger.exception("exception in hook_code")
sys.exit(-1)
好了,跑一下,算出来的结果和联手机签名的结果一致,收工
三、总结
验算是个好习惯
关注微信公众号,最新技术干货实时推送
文章作者 奋飞
上次更新 2020-12-01
许可协议 奋飞安全原创,转载请注明出处。