用户
搜索

[客户端安全] 代码混淆之道(一)

  • TA的每日心情
    开心
    2017-10-30 18:17
  • 签到天数: 54 天

    连续签到: 1 天

    [LV.5]常住居民I

    i春秋作家

    Rank: 7Rank: 7Rank: 7

    26

    主题

    90

    帖子

    943

    魔法币
    收听
    0
    粉丝
    8
    注册时间
    2016-7-3

    i春秋签约作者

    发表于 2017-4-6 00:46:05 836482
    本帖最后由 penguin_wwy 于 2017-4-5 16:47 编辑

    本文原创作者:penguin_wwy,本文属i春秋的原创奖励计划,未经许可禁止转载!


    我也不知道有了一之后会不会有二、三、四。。。凑合着看吧
    20170405202721.jpg
    代码混淆是软件保护技术的一种,而且是最重要却又最难以捉摸的一类(这话不是我说的,是Christian Collberg和Jasvir Nagra说的)。
    说它难以捉摸是因为很难明确定义,很难设计出切实有效的混淆算法,也很难针对混淆算法的质量进行评估。
    说它很重要是因为如果能在它定义的问题上取得一致,并设计出强壮的算法,我们就可以解决许多安全和密码学上的实际问题。

    一、程序分析之路
    有过逆向经验的盆友们都会运用各种各样的工具对程序进行分析,比如利用OD对程序进行调试、IDA分析函数的控制流程、分析函数间的调用关系,这些都是分析程序的方法。
    破解者使用的程序分析技术大致可以分为两大类:静态分析——通过分析代码获取信息;动态分析——通过运行程序收集信息。
    对于程序的静态分析又包括但不限于以下几种方法:
    1、控制流分析,也就是画出程序运行的流程图
    2、数据流分析,获得变量使用的保守信息
    3、数据依赖分析,变量间的依赖关系(赋值、使用、判断顺序等等)
    4、别名分析,在程序运行的某个时间上多个变量必然或可能指向同一个内存地址
    5、切片,对目标变量的影响
    6、抽象解析,定性而不是定量的判读(比如偶数A和B,那么 (A + B)% 2 == 0必然成立 )
    动态分析包括但不限于调试、剖分、trace等等手段
    此外反汇编、反编译是对无源码程序分析的必经之路。以上这些是破解者常用的甚至必须的对针对软件进行攻击的手段。

    二、代码混淆的价值
    所谓混淆,就是针对需要被保护的程序P,经过混淆后转换为P',P和P'的行为保持一致,但是攻击者很难从P'中获取想要的信息。这里的很难指攻击者在分析P'时需要付出比P多的资源(时间、人力)才能从P'中获得和P一样的信息,这个可以是验证码、敏感的个人信息、软件核心运行流程等等。
    代码混淆同样也分为针对静态分析的静态混淆和针对动态分析的动态混淆。
    静态混淆在程序执行前代码便固定下来了,典型的比如压扁控制流、复杂化控制流、不透明谓词等。动态混淆自然是执行时代码仍在变化,比如代码自修改、程序状态机等等。

    三、一种简单的混淆算法——OBFLDK算法
    该算法基本思路就是把程序中的一个无条件转移指令替换成调用一个跳转函数的指令。在正常的思维中函数执行完成后应该返回到函数调用位置的下一条指令
    1.PNG
    而之所以调用函数会返回到函数调用的下一条指令,是因为在call指令执行的时候,next指令的地址被保存起来,也就是函数的返回地址。那么当函数返回的时候,返回地址就会被写入到PC寄存器中,从而开始执行函数调用的下一条指令。如果我们修改了函数的返回地址,那不就意味着我们可以控制函数返回之后下一条被执行指令的地址了吗
    2.PNG
    可以看到,我们通过一个jump_function保持原有的代码code2——>code3的执行顺序不变,而在紧接jump_function的地方,也就是默认在函数调用后被执行的位置插入的是垃圾代码。那么原有的CFG(控制流图)由
    code1——>code2——>code3
    变成
    code1——>code2——>jump_function——>垃圾代码——>code3
    而这段垃圾代码在程序当中是永远不会被执行的,也就是说我们可以把它写成任何东西都不会影响到程序本身的正确性


    下面我们来做一个简单的例子,为了方便我们计算返回地址的位置,我们可以借助宇宙第一IDE——Vistual Studio的反汇编功能
    首先准备一个灰常简单的函数
    [C++] 纯文本查看 复制代码
    int setFunc(int *val) {
            *val += 5;
            return 0;
    }

    然后我们开始对他进行修改,在return 0之前插入我们的跳转函数和垃圾代码
    [C++] 纯文本查看 复制代码
    int setFunc(int *val) {
            *val += 5;
            jmpFunc();
                    
            getEIP();
            _asm {
                    sub                eax, 05h
                    jmp                eax
            };
            return 0;
    }

    jmpFunc就是跳转函数,这条函数会将返回地址设置为return 0所在的位置
    [C++] 纯文本查看 复制代码
    int jmpFunc() {
            _asm {
                    mov                eax, [ebp+04h]        //取出返回地址
                    add                eax, 0ah                //定位到return 0
                    mov                [ebp+04h], eax        //写回返回地址
            }
            return 0;
    }

    _asm是关键字,花括号内跟随的是汇编代码。
    根据x86的调用规则,函数的返回地址会在保存在栈上EBP+4的位置,把返回地址保存到eax寄存器,然后根据计算将返回地址定位到return 0
    计算过程为设置好断点开始debug,然后alt+8打开VS的反汇编窗口
    3.PNG
    上一个箭头就是此时eax保存的地址,下一个就是我们希望跳转的位置,计算一下差10个字节,所以给eax加上0ah
    主函数
    [C++] 纯文本查看 复制代码
    int main()
    {
            int a = 10;
            setFunc(&a);
            char *str = "this is good";
            printf("%s\n", str);
            getchar();
            return 0;
    }
    如果执行成功会输出this is good
    至于中间的垃圾代码,我们可以看到是一个死循环
    [C++] 纯文本查看 复制代码
    void getEIP() {
            _asm {
                    xor                eax, eax
                    mov                eax, [ebp+4]
            }
    }

    4.PNG
    执行成功

    进一步的,我们说过这段垃圾代码可以是任何东西,我们可以在垃圾代码所在的位置上填充任何东西。而由于这些代码紧接在函数调用之后,所以IDA这类的反汇编工具会把这些字节识别为可执行代码
    用010Edit打开我们编译生成的可执行程序,然后找到那段垃圾代码
    5.PNG
    一共10字节,把他们换成hello world的大写字母
    6.PNG
    程序可以正常执行,丢到IDA中,找到对应的位置
    7.PNG
    从D0到D9位置就是我们大写的hello world,但是IDA把它们全都识别为可执行代码。。。WTF!

    本帖被以下淘专辑推荐:

    请叫我加固工程师
    http://penguin-wenyang.wang
    yyyxy 管理员 六国战旗移动展示平台! 秦 楚 燕 魏 齐 赵
    来自 5#
    发表于 2017-4-13 11:16:47
    文章奖励介绍及评分标准:http://bbs.ichunqiu.com/thread-7869-1-1.html,如有疑问请加QQ:286894635!
    奖金
    点评
    50
    前面的简介写的非常易懂,后面也不错,可惜较为简短,下次加油

    欢迎加入i春秋QQ群大家庭,每人只能任选加入一个群哦!投稿请加我QQ:286894635。
    i春秋-楚:533191896
    i春秋-燕:129821314
    i春秋-齐:417360103
    i春秋-秦:262108018
    使用道具 举报 回复
    创想科技时代 版主 i春秋官方指定技术渣 i春秋认证
    沙发
    发表于 2017-4-6 09:21:25
    沙发
    生命必须要有裂缝,阳光才能照射进来
    使用道具 举报 回复
    板凳
    不服你TMD来打我啊!
    使用道具 举报 回复
    地板                           
    使用道具 举报 回复
    试问,这样对原生功能没有影响吗。
    使用道具 举报 回复
    发表于 2017-4-17 14:39:08
    代码描绘人生 发表于 2017-4-15 06:49
    试问,这样对原生功能没有影响吗。

    没有
    请叫我加固工程师
    http://penguin-wenyang.wang
    使用道具 举报 回复
    学习
    使用道具 举报 回复
    发表于 2017-5-20 07:05:23
    学习一波               
    使用道具 举报 回复
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册