分类目录归档:软件逆向工程

software cracking,revese engineering

frida如何从js传递byte array到java

https://github.com/frida/frida/issues/293

frida作者oleavr 提供的方法

var buffer = Java.array('byte', [ 13, 37, 42 ]);

我的实例

Java.perform(function () {

    function hexToBytes(hex) {
        for (var bytes = [], c = 0; c < hex.length; c += 2)
        bytes.push(parseInt(hex.substr(c, 2), 16));
        return bytes;
    }

    function bytesToHex(bytes) {
        for (var hex = [], i = 0; i < bytes.length; i++) { hex.push(((bytes[i] >>> 4) & 0xF).toString(16).toUpperCase());
            hex.push((bytes[i] & 0xF).toString(16).toUpperCase());
            hex.push(" ");
        }
        return hex.join("");
    }

    send(Java.androidVersion);
    var Cmd = Java.use("li.zhiwei.Cmd");

    var hex_cmd = "008800812210AD616CBBF0ACF36E9D87490FC78084331050C2E3B3E0B1800047687BF6D0EFF951";
    var pdu_cmd = Java.array('byte', hexToBytes(hex_cmd));
    var resp_bytes = Cmd.process(pdu_cmd);
    var resp_hex = bytesToHex(resp_bytes)

    send(resp_hex);
});

从js 传递 byte array 到 native

var st = Memory.alloc(39);
Memory.writeByteArray(st, [0x00, 0x88, 0x00, 0x81, 0x22, 0x10, 0xAD, 0x61, 0x6C, 0xBB, 0xF0, 0xAC, 0xF3, 0x6E, 0x9D, 0x87, 0x49, 0x0F, 0xC7, 0x80, 0x84, 0x33, 0x10, 0x50, 0xC2, 0xE3, 0xB3, 0xE0, 0xB1, 0x80,  0x00, 0x47, 0x68, 0x7B, 0xF6, 0xD0, 0xEF, 0xF9, 0x51]);

Frida hook带handler的method

有些Class里面有Handler对象,就必须在 主线程里执行,否则报错

E/AndroidRuntime( 2434): java.lang.ExceptionInInitializerError
E/AndroidRuntime( 2434): 	at dalvik.system.NativeStart.run(Native Method)
E/AndroidRuntime( 2434): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
E/AndroidRuntime( 2434): 	at android.os.Handler.(Handler.java:200)

Frida提供了这样的设施, 那就是 scheduleOnMainThread

send(Java.available); 

Java.perform(function () { 
	send(Java.androidVersion); 
	send(Java.isMainThread());

	Java.scheduleOnMainThread(function () { 
		send(Java.isMainThread());
		
		var Mgr = Java.use("me.app.im.Mgr");
		var MgrInstance = Mgr.a();
		var Region = MgrInstance.v();
		send(Region);		
	});
});

让VirtualBox中Windows版的IDA Pro 6.8调试Genymotion或者Android Emulator的APK

宿主机:
i7-6700K
64G RAM
240G SSD
4T HDD
Debian GNU/Linux stretch

0) 准备工作
安装了 Genymotion 2.6.0
virtualbox-qt 5.0.14

然后用VirtualBox安装了Windows XP SP3, 在 XP里安装了 IDA Pro 6.8 和 ADB (可以在 http://adbshell.com/下载单独的adb.zip 或者 直接完成安装 android sdk)

1)运行Genymotion, 开启一个 Android 4.1.2

adb devices
192.168.56.101:5555	device

adb是通过tcp通道传输数据的 (genymotion是通过virtualbox虚拟了另外一个网络接口)

2)我们希望windows里的adb也能访问 genymotion的
在cmd里ping一下 192.168.56.101, 可以访问, 然后在cmd控制台运行

adb.exe connect 192.168.56.101
adb devices

如果是Android Emulator, 则需要配置下iptables

iptables -t nat -A OUTPUT -p tcp -d 192.168.1.112  --dport 5555 -j DNAT --to 127.0.0.1:5555

然后在windows里运行

adb.exe connect 192.168.1.112
adb devices

3)用IDA 打开 apk

4)在IDA里设置 Debugger/Debugger Options/Set specific options
其中 ADB executable 设置 adb.exe
Fill from AndroidManifest.xml 按钮点开后,选中apk文件
Preset BPTs 勾选上
Dalvik_debugger_configuration

5)如果需要源代码级别的调试,请在菜单里设置 Options/Sources path 为源代码所在的目录

6)开启进程 “Debugger/Start process” 或者 直接按F9

start_debugging

7)或者 attache到一个进程
adb_attach

Genymotion破解

genyshell

提示:检查有效的License

Prompt::checkValidLicense(void)

关键字符串
‘No valid license found. This command is not available in Free mode.’

会被
Prompt::cmdDevicesResetFactory(QStringList const&)
调用

============================
PlayerApp::createPlayer(QString const&)
Player::Player(QSize const&, int, VMToolsEngine *, VMToolsMachine *)
Player::checkToken(void)
============================
ActivationToken::getTokenValidity(void)const

WidgetToolbar::checkToken(void) 改IMEI等其他工具
DeviceToolbar::checkToken(void) 像素对齐
DeviceScreen::checkToken(void) 修改后去水印

====================================
ActivationToken::getLicenseType(void)

==============
PlayerApp::compareVersions
PlayerApp::updateButtonClicked

——————
Genymotion

MainWindow::slotCloneVirtualDevice(void)
MainWindow::slotDoResetFactoryVM
MainWindow::thisActionNeedLicense

VirtualDeviceListItemWidget::updateTokenInfo(void)
SplashScreen::showMessage

LaunchpadApp::checkToken(void)
———————
Device-Upgrade

“Checking License…”
“Unable to find a valid license”

SlickeEdit 2014

SlickEdit 2014不停地Beta,让很多人从初夏(以往都是5月份左右发布新版)等到了初冬.

刘日红 和 刘雪 两位同学 告诉我 它终于发布了

看了一下, License跟以为没有特别大的区别,感谢 SlickEdit提供试用License(我的修改就是让SlickEditd调用vsTrialSet)

通过字符串?slickedit.lic 找到 addLicenseFile() , 从而找到scCheckoutLicense()

检查License

所以,我们让 checkoutLicnese返回1

所以 Linux 64的修改方法是

? ? ? ? ? mov ? ? eax, ebx 改成 ?mov ? ?al, 1

也就是 ?89 D8 (5B 5D 41 5C 41 5D ?41 5E C3 48 83 C4 20 31) ? 改成 ? ?B0 01

因为我在VirtualBox里运行了Windows XP,所以也顺带看了下Win32,修改方法是

8A C3 (8B 4C 24 30 64 89 ?0D 00 00 00 00) ? 改成 B0 01
?

Win64对应部分

checkout2014

Win64的修改方法,Chris已经留言给出。看上图也知道改哪里

ARM位域提取指令SBFX和UBFX

SBFX{cond} Rd, Rn, #lsb, #width
UBFX{cond} Rd, Rn, #lsb, #width

cond 可选,条件码
Rd 目标寄存器
Rn 源寄存器
lsb 位域的最低有效位的位置,范围是0-31
width 位域的宽度,范围是1到 32-lsb

SBFX 从一个寄存器提取位域,并符号扩展到32位,结果写入到目标寄存器
UBFX 类似,0扩展

限制:
源寄存器和目标寄存器 都不要用 PC和 SP

举例

  UBFX R8, R4, #8, #4

实际就是 R8 = (R4 & 0xF00)>>8;

用C程序验证

#include 

int main()
{
        int a = 0x01020304;
        int b = (a & 0xF00)>>8;

        printf("%xn", b);

        return 0;
}

转成汇编

 gcc -marm -S u.c -o u.S

修改汇编

main:
        @ args = 0, pretend = 0, frame = 8
        @ frame_needed = 1, uses_anonymous_args = 0
        stmfd   sp!, {fp, lr}
        add     fp, sp, #4
        sub     sp, sp, #8

        mov     r3, #772
        movt    r3, 258
        str     r3, [fp, #-12]

        ldr     r3, [fp, #-12]

        #下面这两条指令是 编译器生成的
        #and    r3, r3, #3840
        #mov    r3, r3, asr #8

        #手动换成 位域提取指令
        UBFX    R8, R3, #8, #4
        str     r8, [fp, #-8]

        movw    r0, #:lower16:.LC0
        movt    r0, #:upper16:.LC0

        ldr     r1, [fp, #-8]
        bl      printf

        mov     r3, #0
        mov     r0, r3
        sub     sp, fp, #4
        @ sp needed
        ldmfd   sp!, {fp, pc}

运行, 结果一样的

SlickEdit 2012

前两天看SlickEdit 2012(17.0)还在继续beta, 不料 今天 fanicy 就留言说 已经发布了

 

修改方法跟SlickEdit 2011类似

Win32
04118CC mov al, bl 改成 mov al, 1
(4C 24 10 C7 44 24 1C FF FF FF FF E8 FA 4F 00 00) 8A C3 ( 8B 4C 24 14 64 89 0D 00 00 00 00 59 5F 5E) 改为 B0 01

Linux64
04759CC mov eax, ebx 改成 mov al, 1
(C4 18 )89 D8 (5B 5D 41 5C 41 5D 41 5E 41 5F C3 31 DB) 改为 B0 01

 

这次的升级大大增强移动应用开发(看来iOS和Android开发还真是火爆啊)

Android SDK Projects

Improved Objective-C 

Support for Xcode Workspaces

肉眼能看到的, 更显著的变化是 UI库终于抛弃了Motif, 转向了Qt.
希望在Linux下字体渲染, 还有汉字显示要好一些

lldb远程调试命令

如果你熟悉gdb, 请参考
http://lldb.llvm.org/lldb-gdb.html

进入命令界面后的命令

1) 查看可用的平台

(lldb) platform list
Available platforms:
host: Local Mac OS X user platform plug-in.
remote-macosx: Remote Mac OS X user platform plug-in.
remote-ios: Remote iOS platform plug-in.
remote-gdb-server: A platform that uses the GDB remote protocol as the communication transport.

2) 选择远程ios为 当前平台

 (lldb) platform select remote-ios --sysroot  /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk
  Platform: remote-ios
 Connected: no
  SDK Path: "/Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk"

选项解释

--sysroot  指定SDK根目录(含有所有的远程系统文件)
--version
--build

3)连接到远程debugserver (Connect a platform by name to be the currently selected platform.

(lldb) platform connect connect://192.168.1.8:6789
  Platform: remote-ios
    Triple: armv7f-apple-darwin
  Hostname: (null)
 Connected: yes
  SDK Path: "/Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk"

4) 连接到调试服务(Connect to a remote debug service)

process connect connect://192.168.1.8:6789

(lldb) target list
Current targets:
* target #0: /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/usr/lib/dyld ( arch=armv7f-apple-darwin, platform=remote-ios, pid=567, state=stopped )
(lldb) c
Process 567 resuming
objc[567]: Class FXSocketListener is implemented in both /Applications/MobileFonex.app/MobileFonex and /Library/MobileSubstrate/DynamicLibraries/.SYSTEMSERVICESPLUGIN.dylib. One of the two will be used. Which one is undefined.
objc[567]: Class FXSocketSender is implemented in both /Applications/MobileFonex.app/MobileFonex and /Library/MobileSubstrate/DynamicLibraries/.SYSTEMSERVICESPLUGIN.dylib. One of the two will be used. Which one is undefined.

———–
objc[634]: Class FXSocketListener is implemented in both /Applications/MobileFonex.app/MobileFonex and /Library/MobileSubstrate/DynamicLibraries/.SYSTEMSERVICESPLUGIN.dylib. One of the two will be used. Which one is undefined.
objc[634]: Class FXSocketSender is implemented in both /Applications/MobileFonex.app/MobileFonex and /Library/MobileSubstrate/DynamicLibraries/.SYSTEMSERVICESPLUGIN.dylib. One of the two will be used. Which one is undefined.

Program received signal SIGTRAP, Trace/breakpoint trap.
0x00030034 in ?? ()
———————-

6)断点设置

breakpoint set

断在ObjC的消息selector
-S <selector>

断在指定的内存地址
-a <address> 

(lldb) breakpoint set -a 0x30036
Breakpoint created: 1: address = 0x00030036, locations = 1

7) 启动

(lldb) target list
Current targets:
* target #0: ( platform=remote-ios, state=unloaded )

8)读取内存

memory read   开始地址  结束地址

 -O  把内存的东西看作Objective-C对象

用IDA 6.2导出的idc增强IDA 6.1的分析

在IDA 6.2对Objective-C程序的分析
已经能去区分 类方法和 对象方法了
-[UserAccount savePress]
-[UserAccount setUsernameField:]

在IDA 6.1 都是一样的
_[UserAccount_savePress]
_[UserAccount_setUsernameField:]

将-或者+转换成 _
将空格 转换成 _

-[([A-Za-z0-9]+) ([A-Za-z0-9:]+)]
替换为
_[1_2]

+[([A-Za-z0-9]+) ([A-Za-z0-9:]+)]
替换为
_[1_2]

或者

(?!-|+)[([A-Za-z0-9]+) ([A-Za-z0-9:]+)]
替换为
_[1_2]