逆向杂记

2019-08-08  本文已影响0人  浪淘沙008

逆向笔记

Mach-O文件结构


指令集合

file name       //查看文件 
lipo -info MachOName        //查看文件支持的架构类型
lipo mackoName -thin armA -output armAName  //将通用二进制文件拆分为单一架构的文件
lipo -create armA armB -output armAB        //将A、B两种架构合并为AB架构
otool指令
otool -f MachO  //查看胖二进制文件macho文件的头信息
otool -l MachOName  //查看通过查看输出的cryptid可以判断是否加壳



dyld(苹果动态连接器)


Hook概述


越狱工具的使用

Chisel指令列表

plass   viewName    输出控件的层级结构
pviews  viewName    打印view层次
methods view        打印view下的方法列表
pinternals viewAds  打印view的属性等
fvc name    通过名称查找控制器对象
fvc -v ctlAds       查找控制器对象信息
pvc  打印出当前控制器层级结构
taplog  将点击存在相应事件的控件打印输出
flicker viewAds 使对应的控件闪烁
vs viewAds  进入一种可以切换界面的状态

LLDB

search class        查找对象
sbt     输出恢复符号的栈信息
b -a methedAds  通过地址给方法设置断点

Cycript

cycript -r 10.37.34.175:6666    通过网络附加于手机上的某个进程
UIWindow.keyWindow()    输出当前的window
[UIApplication sharedApplication]  输出sharedApplication对象
*#address       获取对象的成员变量
keyWindow.recursicveDescription()       查看所有的子view
pactions(#address)  输出地址对象所关联的方法
rp(#address)        输出地址对象的响应者链条
UIApp.keyWindow.recursiveDescription().toString()  有格式的输出当前子控件
#0x149c07620.allTargets()       输出按钮地址为0x149c07620的target
#0x149c07620.allControlEvents() 输出地址为0x149c07620按钮的事件
[#btnAds actionsForTarget:#targetAds forControlEvent:btnEvent];  输出当点击btn、target为targetAds时调用的方法        
class-dump -H MachO -o 输出的头文件       取出macho文件的头文件并输出
#0x1262a40a0.nextResponder()    查找0x1262a40a0的下一级相应者
#0x1262a40a0.subviews()  查找0x1262a40a0的子控件



Logos语法

%group groupName1 
分组,需要进行初始化
%end
%group groupName2 
分组,需要进行初始化
%end
------------
构造函数
%ctor {
    //可在此处根据应用信息进行分类加载
    %init(groupName1)%init(groupName2)
}
-----------
%log    输出栈所带的函数
%orig   调用原始方法
%new    给某个对象添加方法,不需要%end

插件使用

SSH登陆流程


ssh指令
ssh-keygen -R  ip   删除ip对应的公钥

免密登录流程


scp 文件名 目标路径    将目标文件copy带目标路径文件中
ps -A | grep appName    app在手机中的路径
otool -l MachOName | grep crypt     查看macho文件是否为加密

砸壳

脱壳工具

r   读权限
w   写权限
x   执行权限
chmod +x Clutch      给Clutch添加执行权限
Clutch -i       列出可砸壳的应用
Clutch -d   应用id        对手机中的某个应用砸壳
Device/var/mobile/Documents/Dumped   砸过壳的ipa所在位置
当Clutch2.4移动到/usr/bin目录下后要重命名为Clutch
编译后将dumpdecrypted.dylib文件导入到手机的根目录
直接运行
DYLD_INSERT_LIBRARIES=应用路径      就可在根目录获得砸壳后的应用

Theos 使用

ps -A   列出手机中所有的进程
ps -A | grep AppName    输出当前手机中名字为AppName的应用
cycript -p AppName      将应用依附在AppName上
export THEOS_DEVICE_IP=127.0.0.1
export THEOS_DEVICE_PATH=12345

debugserver

debugsever *:12346 -a HelloTrip     手机输入进入等待连接状态
lldb    电脑端输入lldb进入调试状态
process connect connect://10.37.34.175:12346   电脑端输入连接手机(wifi连接)

//通过usb连接
python tcprelay.py -t 22:12345 12346:12346   在启动ssh连接时增加映射端口
process connect connect://localhost:12346   在电脑端进行lldb连接时执行的命令
    
process interrupt   在lldb连接的情况下进入断点状态

使用MonkeyDev中的tweak来hook项目

tweak原理

dyld代码分析

配置monkeydev调用方法输出

[图片上传失败...(image-c7b586-1565677706001)]

恢复符号表

make restore-symbol
./restore-symbol MachOName -o outputMachOName

logs语句

MSHookIvar<变量类型 *>(class, "成员变量名称")    //hook成员变量

ptrace防护

#import <sys/ptrace.h>
进入之后复制其中的代码并粘贴到自己创建的头文件中

使用方法导入自己创建的头文件
    /**
     arg1:ptrace 要做的事情 PT_DENY_ATTACH为禁止附加
     arg2:要操作的进程的id 0代表本进程
     arg3:地址
     arg4:数据
     */
    
ptrace(PT_DENY_ATTACH, 0, 0, 0);

debug调试检测

问题------------------

混淆

//隐藏UserInfoClass字段在反汇编工具中的展示可在pch文件中声明,如此则在代码中不会显示UserInfoClass的字段
#define UserInfoClass  fhdjskafd

//eg:如果一个字符串为GPF的一个字符串不想让别人获取到可提高反汇编难度,通过以下方法保存的字符串不会在常量区直接显示,增加了汇编的难度

#define STRING_ENCRYPT_KEY 0xAC

static NSString * AES_KEYINFO() {
    unsigned char key[] = {
        (STRING_ENCRYPT_KEY ^ 'G'),
        (STRING_ENCRYPT_KEY ^ 'P'),
        (STRING_ENCRYPT_KEY ^ 'F'),
        (STRING_ENCRYPT_KEY ^ '\0'),
    };
    unsigned char * p = key;
    while (((*p) ^= STRING_ENCRYPT_KEY) != '\0') {
        p++;
    }
    return [NSString stringWithUTF8String:(const char *)key];
}

防护之ptrace隐藏

//通过该方法调用的ptrace无法被fishhook所hook
#import <dlfcn.h>
void dlopenAction() {
    unsigned char funcStr[] = {
        ('a' ^ 'p'),
        ('a' ^ 't'),
        ('a' ^ 'r'),
        ('a' ^ 'a'),
        ('a' ^ 'c'),
        ('a' ^ 'e'),
        ('a' ^ '\0'),
    };
    unsigned char * p = funcStr;
    while (((*p) ^= 'a') != '\0') p++;
    
    //通过dlopen拿到句柄
    void * handle = dlopen("/usr/lib/system/libsystem_kernel.dylib", RTLD_LAZY);
    
    //定义函数指针
    int (* old_ptrace)(int _request, pid_t _pid, caddr_t _addr, int _data);
    
    
    if (handle) {
        old_ptrace = dlsym(handle, (const char *)funcStr);
        if (old_ptrace) {
            old_ptrace(PT_DENY_ATTACH, 0, 0, 0);
        }
    }
}

syscall(26, 31, 0, 0);      //26为ptrace在syscall中的方法编号, 31位ptrace的第一个参数
   asm volatile (
                  "mov x0,#26\n"
                  "mov x1,#31\n"
                  "mov x2,#0\n"
                  "mov x3,#0\n"
                  "mov x16,#0\n"
                  "svc #0x80\n" //触发中断
    );
    
 asm volatile (
                  "mov x0,#31\n"
                  "mov x1,#0\n"
                  "mov x2,#0\n"
                  "mov x3,#0\n"
                  "mov x16,#26\n"
                  "svc #0x80\n" //触发中断
    );
    

越狱检测

    char * dlname = getenv("DYLD_INSERT_LIBRARIES");
    NSLog(@"%s", dlname);
    
    当dlname有值的时候为越狱状态,无值的时候为非越狱状态

防止重签名

上一篇 下一篇

猜你喜欢

热点阅读