开课:
xwj 发表于 2009-3-5 12:28 侃单片机 ←返回版面 | 17楼: “红杏出墙装疯拳”详解--第一招: |
/*--------------------------------------------- HotTask51系统启动函数 void __HotASM_START__(void) 入口: 无 Keil DPTR = &__HotASM_START__[0] R2D1 = DPTR 出口: 无 结果: 二次RETI后继续执行 特点: 本“函数”可以“动态加载” -----------------------------------------------*/ --老x:上面是注释,在中国上过学的都能看懂,就不用啰嗦了 --观众:这还不啰嗦啊?晕! --老x:甭晕啊,这都还没开始呢... HotASM (__HotASM_START__)//(void) --定义个code区的数组,相当于code const unsigned char __HotASM_START__ --为什么呀? --为什么?先去看下HotASM.h啊,里面先一招typedef code const unsigned char HotASM_ARRAY;//类型定义 然后一招#define HotASM(NAME) HotASM_ARRAY(NAME)[]= --嗯,象这样的问题老x以后就不再回答了,免得浪费时间,还把老x也累得要死... {//DPTR保存的是汇编数组函数的首地址__HotASM_START__ #define lable__HotASM_START__Exit ( size_CLR_A() + size_MOV_REG_A() + size_JZ() + size_LJMP() + 2 * size_MOV_A_REG() + 2 * size_ADD_A() + 2 * size_PUSH_REG()) --嗯,这个是用来计算跳转多少个字节的,因为后面有个分支,一个分支分支就会有2个出口,有2个出口当然就会有不同的跳转偏移... --晕,老x今天怎么这么象唐僧啊? --嗯,那就先不管了,其实老x觉得啊,这样子好麻烦啊,还要把中间跳过的指令都复制过来,还要统计中间的字节数,真是麻烦啊~~~,老x觉得啊,可以有更简单的方法啊,比如直接就RETI啊... --少啰嗦,快说正题! --好好,老x接着分析啊~~ asm_CLR_A(), --想不用想,把ACC清零(有什么用呢?) asm_MOV_IE_A(),//关中断 --哦,原来是IE=ACC; 关中断。(那...为什么不干脆CLR EA呢?) asm_JZ(size_LJMP() - 1),//NOP() --A为零跳转(这不是那脱裤子排气吗?A肯定为0啊,刚刚才清过呢) asm_LJMP(0x5500),// --跳过去了,永远运行不到 asm_MOV_A_DPL(), --ACC=DPL; asm_ADD_A(lable__HotASM_START__Exit),//__HotASM_START__0 --加上偏移,进位的话影响CY asm_PUSH_ACC(),//压入跳入地址__HotASM_START__0低8位 --ACC入栈,SP加一 asm_MOV_A_DPH(),// --ACC=DPH; asm_ADDC_A(0), --前面加偏移时可能会进位,把可能的进位加进去 asm_PUSH_ACC(),//压入跳入地址__HotASM_START__0高8位 --ACC入栈,SP又加一;这是堆栈中最高2字节是下一个出口的地址 //lable__HotASM_START__Exit: asm_RETI()//(连续调用RETI二次) --明明只有一次RETI吗,看来老Hotel真是老糊涂了 --RETI和RET的作用可大了它的作用就是把堆栈中最高2字节装入PC(程序地址指针寄存器),把SP-2,这样下一个指令就返回到堆栈中最高2字节对应的地址位置继续执行了 --这就相当于一个可以任意设置跳转位置的LJMP,所有的OS可都要玩到这一招哦 };
首先可以看出XWJ很少“反汇编”,而且C51的汇编应该属于“尿童级”。 asm_CLR_A(), --想不用想,把ACC清零(有什么用呢?) asm_MOV_IE_A(),//关中断 --哦,原来是IE=ACC; 关中断。(那...为什么不干脆CLR EA呢?) asm_JZ(size_LJMP() - 1),//NOP() --A为零跳转(这不是那脱裤子排气吗?A肯定为0啊,刚刚才清过呢) asm_LJMP(0x5500),// --跳过去了,永远运行不到
在这4句里,隐藏了反逆向技术。 首先,asm_CLR_A(),得到一确定的事情,ACC肯定为0 asm_MOV_IE_A(),//关中断,因为是初始化函数,就应该初始化干净。 否则软中断后,EX0等IE内的5个中断标志不会被清除。 下面这2句谁能看出来??? asm_JZ(size_LJMP() - 1),//NOP() --A为零跳转(这不是那脱裤子排气吗?A肯定为0啊,刚刚才清过呢) asm_LJMP(0x5500),// --跳过去了,永远运行不到
脱裤子排屁是臭逆向者的~~~因为此时ACC为0,它跳入了asm_LJMP(0x5500),的第2操作数0x00。 0x00是数据,但代码确实NOP!!! 0x5500就是引诱反汇编去0x5500处折腾的,正常的程序永远不会执行到~~~ 这是系列反逆向技术的一招。请团员们切记!!! 大家可以耐心地debug,可以看到好好的反汇编窗口在执行开始没有NOP指令, 单步到JZ后,在单步发现指令列表突然变化了---出现了NOP!!! 试想,团员们用菜农的“250”招后,谁还再来反汇编??? 晕都晕死它~~~ 俺是“反汇编”的“革命先烈”~~~最近“反水”,所以俺最知道对付“自己人” ~~~ 程序虽小,不晕则好。 有时间继续点评其他HotC51Demo内的小程序~~~ 注意,每个都有课本上学不到的知识~~~ 课毕
HotC51@126.com 2009.3.9于菜地。 团部:http://group.**/1623/
|