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

software cracking,revese engineering

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]

Smali调试

APKTool可以单步调试smali代码, 查看变量, 设置断点

准备
1)调试服务器(DDMS, 是Android SDK的一部分)
DDMS 是Dalvik Debug Monitor Service的缩写
它提供 端口转发, 屏幕捕获, 线程和 heap信息, 已经无线电状态信息, 来电, 短信, 地理位置模拟等等

DDMS同Eclipse集成在一起, 同时也放在SDK的 tool目录下
比如 /home/zhiwei/android-sdk-linux/tools/ddms
ddms可以同 android设备仿真器 或者 真实的物理设备 工作

从Eclipse启动 Window > Open Perspective > Other… > DDMS

从命令行 启动 ./ddms

请参考 http://developer.android.com/guide/developing/debugging/ddms.html

2)调试客户端(通常是IDE)

步骤
1. 将app.apk解码成调试模式, 输出到out 目录
apktool d -d app.apk out

2. 将调试模式的代码 重新生成apk
apktool b -d out

3. 签名,安装,运行新的apk

4. 在Netbeans中, 使用存在的源代码创建新的Java项目, 选择 out 目录作为 工程的根目录, out下面的子目录smali作为源代码目录

5. 运行DDMS, 在列表里找到你的应用并点击它. 注意:端口信息在最后一栏里,
类似于 “86xx/8700″的东西

6. 在Netbeans里, Debug -> Attach Debugger -> select JPDA
并设置port 为 8700(就是你在第5步看到的端口号)
其他地方保持默认,不用修改

7. 调试会话 应该已经启动了: 你可以看到一些log信息, 调试按钮将显示在顶部面板上

8. 设置断点, 不能在 以 . 或者 : 或者 #开始的行 设置断点

9. 在应用程序里 触发 某些行为. 如果你运行在一个断点上, 那么线程将会停下来, 让你单步调试,查看变量等等

我尝试过使用Eclipse, 但是它禁止 在未知行

下载apktool-install-linux-* 和 apktool-* 文件

解压缩到 /usr/local/bin 目录下

export PATH=”$PATH:/tmp/ccc” 保证 aapt 在 path路径下, 否则 build 时报错