利用frida實現遊戲作弊
阿新 • • 發佈:2018-12-05
前言
frida是一款輕量級hook框架,支援js、c,python,所以用它來除錯各種軟體非常便捷,不需要編譯,反覆注入等等
安裝
python環境
pip install frida frida-tools
原始碼地址 https://github.com/frida/frida
下載地址 https://github.com/frida/frida/releases
將frida-server push到手機中,並啟動
除錯
遊戲逆向
該遊戲時il2cpp
的,獲取到遊戲函式偏移。
public void UpdateGold(int addGold) ; // 0x1A05AC
編寫指令碼
啟動遊戲。發現存在反除錯,已經被attach了。
這是咋辦呢?正常情況下,如果是so注入的話,一般有這麼些思路:
- 注入zygot程序,然後由zygot 進行fork,這樣所有app都被注入
- 預載入程式時暫停(
am start -D -n XXXXX
啟動),然後ptrace注入,在detach - 修改原始碼,編譯過程複雜,耗時間
這裡frida支援預載入注入,編寫指令碼main.py
。
# -*- coding: utf-8 -*-
# @Author: saidyou
# @Date: 2018-07-10 01:51:54
# @Last Modified by: saidyou
# @Last Modified time: 2018-12-05 10:24:10
# -*- coding: utf-8 -*-
import frida
import sys
import os
from struct import *
import traceback
package_name = 'com.ztgame.yyzy'
# package_name = 'com.sdg.woool.xuezu'
#send
js_name = 'yyzy.js'
is_launch = 1
pwd = sys.path[0]
script = None
session = None
protocal_list = []
def port_forward():
os.system('adb forward tcp:27042 tcp:27042')
os.system('adb forward tcp:27043 tcp:27043')
def get_js_code():
buf = open(pwd+'\\'+js_name).read()
return buf
def send_continue():
script.post({"type": "continue"})
def witch_pro_num(pro_num):
for line in protocal_list:
if line.find(pro_num)+1:
print line[:-1]
return line
def on_message(message, data):
global lua_num
try:
if data and len(data)>0:
aaaa=''
else:
return
if message['payload'].find('save')+1:
open('e:\\'+message['payload'],'wb+').write(data)
elif message['payload']=='send' :
# print type(data),len(data),`data`
protocal_num = unpack('<H',data[:2])[0]
pro_buf = witch_pro_num(hex(protocal_num))
if pro_buf.find('pt_state_skill')+1:
send_continue()
elif message['payload'] == 'Assembly-CSharp.dll' :
open('e:\\Assembly-CSharp.dll','wb').write(data)
else :
# print message['payload']
file_type = '.lua'
if data[:4]=='\x1bLua':
file_type = '.luac'
full_path = 'e:\\lua\\'+message['payload'].replace('/','\\')+file_type
full_dir = full_path[:full_path.rfind('\\')]
if os.path.exists(full_dir) == False:
os.system('mkdir '+full_dir)
print full_path
open(full_path,'wb+').write(data)
except:
traceback.print_exc()
def attach():
global script
global session
device = frida.get_usb_device()
session = device.attach(package_name)
script = session.create_script(get_js_code())
script.on('message', on_message)
script.load()
sys.stdin.read()
def launch():
global script
global session
# local
device = frida.get_usb_device()
# remote
#device = frida.get_device_manager().add_remote_device('192.168.123.20')
p1 = device.spawn([package_name])
session = device.attach(package_name)
script = session.create_script(get_js_code())
script.on('message', on_message)
script.load()
device.resume(p1)
sys.stdin.read()
def main():
reload(sys)
sys.setdefaultencoding('utf-8')
port_forward()
if is_launch:
launch()
else:
attach()
if __name__ == '__main__':
main()
hook程式碼yyzy.js
/*
* @Author: saidyou
* @Date: 2018-11-27 10:41:42
* @Last Modified by: saidyou
* @Last Modified time: 2018-12-04 19:43:31
*/
function get_func_by_offset(module_name,offset){
module=Process.getModuleByName(module_name)
addr=module.base.add(offset);
return new NativePointer(addr.toString());
}
// UpdateGold 0x1A05AC
function attach_gold(so_path){
func = get_func_by_offset("libil2cpp.so",0x1A05AC)
console.log('[+] hook '+func.toString())
Interceptor.attach(func, {
onEnter: function (args) {
console.log('**********************')
var1 = args[1].toInt32()
args[1] = ptr(999)
console.log('[!] modify UpdateGold from '+var1+' to 1000')
console.log('[*] '+args[1].toString())
},
onLeave: function (retval) {
}
});
}
var is_matched = false;
function attach_matched(so_path){
if(so_path.indexOf('libil2cpp.so')<0 || is_matched == true){
return
}
is_matched = true
console.log('[*] '+so_path)
attach_gold(so_path)
}
function hook_dlopen(){
// func = get_func_by_offset('libc.so','dlopen')//492d
// func = Module.findExportByName("linker","dlopen") //33ed
var func = get_func_by_offset('linker',0x2C31 )
console.log('[+] dlopen '+ func.toString())
Interceptor.attach(func, {
onEnter: function (args) {
this.so_path = Memory.readCString(args[0])
console.log('[*] ')
},
onLeave: function (retval) {
// console.log(this.so_path)
attach_matched(this.so_path)
}
});
}
hook_dlopen()
// hook_open()
// addr = DebugSymbol.getFunctionByName('dlopen')
// console.log(addr)
這裡修改的時金幣,點選購買,金幣增加,完美作弊。