前言:对telock的怨念要追溯到 半年前  那时候 比现在还菜的多 现在待业在家 有了时间 分析完后 发现telock 其实很简单
详细的分析不发了  只是简单的总结下里面用到的 一些tricks 至于花指令以及过异常 都是很简单的东西
略过不提
附件里的repair是修复过的  样本是个木马 调试请小心

关注点:
1:经典的  硬件断点 外加异常  做密钥  对于这个  论坛里搜telock 有很多都讲到这个了  所以 我就不说了
而密钥的计算方法 实际上 是对一段内存 计算crc然后  异或出  最后的密钥  
硬件断点 外加异常  影响了 6dd118的值 顺利过了的话 crc正确 最后的密钥自然也就正确了
如下:
//第一次计算CRC  校验6dd000~6de992  校验值存放于edx
006DD7EA    8D75 81           LEA ESI,DWORD PTR SS:[EBP-7F]            ;定位到 最后一节
006DD7ED    BB 92190000       MOV EBX,1992                             ;校验的字节数
006DD7F2    8D51 FF           LEA EDX,DWORD PTR DS:[ECX-1]             ;初始值-1
006DD7F5    33C0              XOR EAX,EAX
006DD7F7    AC                LODS BYTE PTR DS:[ESI]
006DD7F8    32C2              XOR AL,DL
006DD7FA    D1E8              SHR EAX,1
006DD7FC    73 08             JNB SHORT tElock_0.006DD806
006DD7FE   /EB 01             JMP SHORT tElock_0.006DD801
006DD800   |90                NOP
006DD801   \35 E195C7CD       XOR EAX,CDC795E1
006DD806    41                INC ECX
006DD807    80E1 07           AND CL,7
006DD80A  ^ 75 EE             JNZ SHORT tElock_0.006DD7FA              ;单个字节  是否校验完
006DD80C    C1EA 08           SHR EDX,8                                
006DD80F    33D0              XOR EDX,EAX
006DD811    4B                DEC EBX
006DD812  ^ 7F E1             JG SHORT tElock_0.006DD7F5

006DD814   /74 02             JE SHORT tElock_0.006DD818
006DD816   |CD 20             INT 20
006DD818   \B9 0D000000       MOV ECX,0D
006DD81D    58                POP EAX
006DD81E    AB                STOS DWORD PTR ES:[EDI]                 ;将堆栈中的函数存放于 原来的地方
006DD81F    83EF 08           SUB EDI,8
006DD822  ^ E2 F9             LOOPD SHORT tElock_0.006DD81D

006DD824    66:3395 551B0000  XOR DX,WORD PTR SS:[EBP+1B55]           ;修正crc
006DD82B    8995 551C0000     MOV DWORD PTR SS:[EBP+1C55],EDX         ;存放crc   [6decd4] = 9346BEE5 实际上 从6decd4开始 是一个和节信息有关的结构struct_telock_2 详见下文

2:对节的处理
经过仔细分析  各个节被压缩过1次 加密2次  节的解密也是比较巧妙的
先把逆出的结构列出来方便理解
struct_telock_2(起始地址6decd4)
{
  +00 decode_key    //对每一节进行2次解密 再解压   这是第2次解密的key 即第一次crc修正的密钥
  +04 deocode_key2       //夹杂在 异常处理中计算出的值 用于壳的后继解密 
  +08 numberofcompress_section//壳压缩加密过的节数目
  +10 checksum1     //用于对解密后的每一节校验 取反即为oep   只要找到这个结构 就可以很轻松的知道oep了
          //幸运的是 这个结构 相对于壳基址是固定的 不幸的是在文件中是加密存储的 无法直接得到OEP

  //numberofcompress_section个 section结构
  section
  {
    +14 section_Rva
    +18 section_size //最高位 为1则代表 需要解压
    +1c compress_seciton_crc// 压缩后节的crc
  }
..............
}
//解密 节 1次
006DDCF4    60              PUSHAD
006DDCF5    8BF3            MOV ESI,EBX                              ; tElock_0.00401000
006DDCF7    BA 499A68C8     MOV EDX,C8689A49
006DDCFC    8BFE            MOV EDI,ESI
006DDCFE    0FB6DE          MOVZX EBX,DH
006DDD01    EB 01           JMP SHORT tElock_0.006DDD04
006DDD03    90              NOP
006DDD04    69DB 73FA736A   IMUL EBX,EBX,6A73FA73
006DDD0A    AC              LODS BYTE PTR DS:[ESI]
006DDD0B    04 ED           ADD AL,0ED
006DDD0D    FEC0            INC AL
............省略一些

//继续解密  2次
006DDFAB    56              PUSH ESI
006DDFAC    57              PUSH EDI
006DDFAD    8BFB            MOV EDI,EBX
006DDFAF    8BF7            MOV ESI,EDI
006DDFB1    8B9D 76D34000   MOV EBX,DWORD PTR SS:[EBP+40D376]              ;6decd4  第一次crc修正值做密钥struct_telock_2.decode_key
006DDFB7    AC              LODS BYTE PTR DS:[ESI]
006DDFB8    EB 02           JMP SHORT tElock_0.006DDFBC
006DDFBA    CD 20           INT 20
006DDFBC    34 9F           XOR AL,9F
006DDFBE    2C C3           SUB AL,0C3
006DDFC0    32C1            XOR AL,CL
006DDFC2    8807            MOV BYTE PTR DS:[EDI],AL
006DDFC4    D2C8            ROR AL,CL
006DDFC6    32C3            XOR AL,BL
006DDFC8    021F            ADD BL,BYTE PTR DS:[EDI]
006DDFCA    12D9            ADC BL,CL
006DDFCC    F6C1 01         TEST CL,1
006DDFCF    75 0F           JNZ SHORT tElock_0.006DDFE0
006DDFD1    D1EB            SHR EBX,1
006DDFD3    F7C3 08000000   TEST EBX,8
006DDFD9    75 05           JNZ SHORT tElock_0.006DDFE0
006DDFDB    D3C3            ROL EBX,CL
006DDFDD    8D1CDB          LEA EBX,DWORD PTR DS:[EBX+EBX*8]
006DDFE0    AA              STOS BYTE PTR ES:[EDI]
006DDFE1    49              DEC ECX
006DDFE2  ^ 7F D3           JG SHORT tElock_0.006DDFB7
//计算crc来校验 校验成功才解压
006DDFE6    8B8F 8AD34000   MOV ECX,DWORD PTR DS:[EDI+40D38A]      ;section_size
006DDFEC    8B87 86D34000   MOV EAX,DWORD PTR DS:[EDI+40D386]      ;seciton_RVa
006DDFF2    F7C1 00000080   TEST ECX,80000000
006DDFF8    74 6A           JE SHORT tElock_0.006DE064             
006DDFFA    81E1 FFFFFF7F   AND ECX,7FFFFFFF
006DE000    0385 62D34000   ADD EAX,DWORD PTR SS:[EBP+40D362]
006DE006    60              PUSHAD
006DE007    8BF0            MOV ESI,EAX
006DE009    8BD9            MOV EBX,ECX
006DE00B    33C9            XOR ECX,ECX
006DE00D    8D41 FF         LEA EAX,DWORD PTR DS:[ECX-1]
006DE010    57              PUSH EDI
006DE011    BF 2083B8ED     MOV EDI,EDB88320
006DE016    33D2            XOR EDX,EDX
006DE018    8A16            MOV DL,BYTE PTR DS:[ESI]
006DE01A    32D0            XOR DL,AL
006DE01C    D1EA            SHR EDX,1
006DE01E    73 02           JNB SHORT tElock_0.006DE022
006DE020    33D7            XOR EDX,EDI
006DE022    41              INC ECX
006DE023    80E1 07         AND CL,7
006DE026  ^ 75 F4           JNZ SHORT tElock_0.006DE01C
006DE028    C1E8 08         SHR EAX,8
006DE02B    33C2            XOR EAX,EDX
006DE02D    46              INC ESI
006DE02E    4B              DEC EBX
006DE02F  ^ 7F E5           JG SHORT tElock_0.006DE016                  //计算 解密后节crc 校验值 在eax中
006DE031    5F              POP EDI
006DE032    F7D0            NOT EAX                                     //对 解密后的 节 进行校验
006DE034    3387 8ED34000   XOR EAX,DWORD PTR DS:[EDI+40D38E]
006DE03A    35 6137E43C     XOR EAX,3CE43761
006DE03F    3385 FED34000   XOR EAX,DWORD PTR SS:[EBP+40D3FE]
006DE045    F7D0            NOT EAX
006DE047    2B85 82D34000   SUB EAX,DWORD PTR SS:[EBP+40D382]
006DE04D    61              POPAD
006DE04E    0F85 27020000   JNZ tElock_0.006DE27B                       //校验失败则跳
006DE054    50              PUSH EAX                                   //section_VA
006DE055    51              PUSH ECX                                   //section_size
006DE056    E8 1A000000     CALL <tElock_0.uncompress>                 //解压
006DE05B    83F8 FF         CMP EAX,-1
006DE05E    0F84 17020000   JE <tElock_0.fail>
006DE064    83C7 0C         ADD EDI,0C
006DE067    4E              DEC ESI
006DE068    7E 06           JLE SHORT tElock_0.006DE070              //处理完毕

3:各个节处理完以后 开始处理 重定位(因为我分析的 是exe无需 重定位 所以简单点了)
对于重定位以及 下面处理的资源 也有个重要的结构
struct_telock_1
{
  +00 iat_Rva   
  +04 reloc_Rva //重定位表RVA
  +08 rsrc_Rva //资源节 RVA
  +0c pack_section //壳所在节的RVA
  +10 real_imagebase//真实的装载基址  运行时写入
  +14 old_imagebase//加壳前原文件的装载基址  判断是否需要重定位
  +18 compress_rsrc//压缩的资源 相对于资源节地偏移 即资源分为压缩 和未压缩两部分
  +1c size_rsrc//压缩后 的那部分资源 大小
}

//这里应该是 处理重定位
006DE177    8BB5 56D34000   MOV ESI,DWORD PTR SS:[EBP+40D356]        //6decb4 = 9f00 重定位表Rva struct_telock_1.iat_Rva
006DE17D    85F6            TEST ESI,ESI
006DE17F    0F84 8B000000   JE tElock_0.006DE210
006DE185    8B95 62D34000   MOV EDX,DWORD PTR SS:[EBP+40D362]       //6decc0 = 400000 实际的image_base      struct_telock_1.real_imagebase
006DE18B    03F2            ADD ESI,EDX
006DE18D    2B95 66D34000   SUB EDX,DWORD PTR SS:[EBP+40D366]       //6decc4 = 400000 原来的image_base      struct_telock_1.old_imagebase
006DE193    74 7B           JE SHORT tElock_0.006DE210             //如果 装载基址相等 则无须重定位
006DE195    8BDA            MOV EBX,EDX
006DE197    C1EB 10         SHR EBX,10
006DE19A    8B06            MOV EAX,DWORD PTR DS:[ESI]
006DE19C    85C0            TEST EAX,EAX
006DE19E    74 70           JE SHORT tElock_0.006DE210            //重定位处理完后从此处 跳出
.............省略点  

4:Iat及资源处理
telock 处理Iat 的过程中 一直在破坏Iat的结构 这样处理完Iat后 内存中没有正确的结构
而且 处理过程中得到的函数地址 都存放在自己申请的内存中 而原文件本应存放函数地址的
地方 全部变成壳中的地址    有兴趣的人跟了看看
只贴几个 关键点
//应该要处理IAT
006DE210    8B95 62D34000   MOV EDX,DWORD PTR SS:[EBP+40D362]        ;6decc0   imagebase = 400000 
006DE216    8BB5 52D34000   MOV ESI,DWORD PTR SS:[EBP+40D352]        ;6decb0   IatRva = 9a0000
006DE21C    85F6            TEST ESI,ESI
006DE21E    0F84 06040000   JE tElock_0.006DE62A
006DE224    03F2            ADD ESI,EDX                              ;IatVa = 49a0000
006DE226    83A5 52D44000 0>AND DWORD PTR SS:[EBP+40D452],0
006DE22D    8B46 0C         MOV EAX,DWORD PTR DS:[ESI+C]             ;IMAGE_IMPORT_DESCRIPTOR.Name1
006DE230    8366 0C 00      AND DWORD PTR DS:[ESI+C],0               ;破坏iat结构.Name1字段
006DE234    85C0            TEST EAX,EAX                             ;修复好iat后 从此处 跳出
006DE236    0F84 EE030000   JE tElock_0.006DE62A
006DE23C    03C2            ADD EAX,EDX                              ;dll_name VA
。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。
// 生成代理api的指令   这样exe->调用Api 变成exe->调用壳->壳调用api
006DE43E    50              PUSH EAX
006DE43F    53              PUSH EBX
006DE440    0FB74424 08     MOVZX EAX,WORD PTR SS:[ESP+8]
006DE445    50              PUSH EAX
006DE446    8D85 14BB4000   LEA EAX,DWORD PTR SS:[EBP+40BB14]             ;6dd472   指令表
006DE44C    0FB618          MOVZX EBX,BYTE PTR DS:[EAX]
006DE44F    FF0C24          DEC DWORD PTR SS:[ESP]
006DE452    7E 09           JLE SHORT tElock_0.006DE45D
006DE454    40              INC EAX
006DE455    03C3            ADD EAX,EBX
006DE457  ^ EB F3           JMP SHORT tElock_0.006DE44C
006DE459    0000            ADD BYTE PTR DS:[EAX],AL
006DE45B    0000            ADD BYTE PTR DS:[EAX],AL
............................
............................
006DE4C6    83A5 FBCA4000 0>AND DWORD PTR SS:[EBP+40CAFB],0F                                 
006DE4CD    8BBD 52D44000   MOV EDI,DWORD PTR SS:[EBP+40D452]        ;6dedb0 存放函数地址的地方
006DE4D3    8B85 5AD44000   MOV EAX,DWORD PTR SS:[EBP+40D45A]        ;6dedb8 FirstThunk     VA
006DE4D9    0385 4ED34000   ADD EAX,DWORD PTR SS:[EBP+40D34E]        ;6decac 函数名RVA偏移
006DE4DF    8B8D 56D44000   MOV ECX,DWORD PTR SS:[EBP+40D456]        ;6dedb4 相对于新分配内存的RVA
006DE4E5    8908            MOV DWORD PTR DS:[EAX],ECX               ;破坏 iat 里的IMAGE_THUNK_DATA
...........................
...........................
006DE5B7    40              INC EAX
006DE5B8    F8              CLC
006DE5B9    66:8943 FE      MOV WORD PTR DS:[EBX-2],AX               ;继续破坏iat结构 IMAGE_IMPORT_BY_NAME 

资源处理没什么说的  解压而已
//处理完IAT  解压资源
006DE62A >  8BBD 5AD34000   MOV EDI,DWORD PTR SS:[EBP+40D35A]                     ;rsrc_rva
006DE630    85FF            TEST EDI,EDI
006DE632    EB 03           JMP SHORT tElock_0.006DE637
006DE634    0100            ADD DWORD PTR DS:[EAX],EAX
006DE636    90              NOP
006DE637    74 32           JE SHORT tElock_0.006DE66B
006DE639    03BD 62D34000   ADD EDI,DWORD PTR SS:[EBP+40D362]                     ;+imagebase = rsrc_va
006DE63F    8B85 6AD34000   MOV EAX,DWORD PTR SS:[EBP+40D36A]                     ;压缩的资源 相对于资源节地偏移
006DE645    85C0            TEST EAX,EAX
006DE647    74 22           JE SHORT tElock_0.006DE66B
006DE649    8B8D 6ED34000   MOV ECX,DWORD PTR SS:[EBP+40D36E]                     ;压缩后 的那部分资源 大小
006DE64F    85C9            TEST ECX,ECX
006DE651    74 18           JE SHORT tElock_0.006DE66B
006DE653    03C7            ADD EAX,EDI
006DE655    0385 72D34000   ADD EAX,DWORD PTR SS:[EBP+40D372]
006DE65B    50              PUSH EAX
006DE65C    51              PUSH ECX
006DE65D    E8 13FAFFFF     CALL <tElock_0.uncompress>                            ;解压资源节
006DE662    83F8 FF         CMP EAX,-1                                            ;关键点(跳过iat后在此处dump) 
006DE665  ^ 0F84 10FCFFFF   JE <tElock_0.fail>
006DE66B    B9 03030000     MOV ECX,303                                           ;解密循环
006DE670    8DBD 30CD4000   LEA EDI,DWORD PTR SS:[EBP+40CD30]                     ;解密起始地址6de68e
006DE676    8BF7            MOV ESI,EDI
006DE678    8A140E          MOV DL,BYTE PTR DS:[ESI+ECX]
006DE67B    8B9D 7AD34000   MOV EBX,DWORD PTR SS:[EBP+40D37A]                     ;前面夹杂在异常中计算出的key    struct_telock_2.deocode_key2

5:下面几乎没什么了  需要注意的就是修改了pe头里的numberofsection值
006DE6B9    FF95 00BB4000   CALL DWORD PTR SS:[EBP+40BB00]           ;VirtualProctectEx 修改pe头 为可读可写
006DE6BF    83C4 04         ADD ESP,4
006DE6C2    40              INC EAX
006DE6C3    48              DEC EAX
006DE6C4    74 0D           JE SHORT tElock_0.006DE6D3
006DE6C6    8BBD 62D34000   MOV EDI,DWORD PTR SS:[EBP+40D362]        ;imagebase
006DE6CC    037F 3C         ADD EDI,DWORD PTR DS:[EDI+3C]            ;pe头
006DE6CF    66:0967 06      OR WORD PTR DS:[EDI+6],SP                ;修改numberofsection

6:oep的出现
006DE745    8B9D 82D34000   MOV EBX,DWORD PTR SS:[EBP+40D382]         struct_telock_2.checksum1
006DE74B    33F6            XOR ESI,ESI
006DE74D    F7D3            NOT EBX
006DE74F    0BF3            OR ESI,EBX
006DE751    75 08           JNZ SHORT tElock_0.006DE75B
006DE753    8D9D A2B64000   LEA EBX,DWORD PTR SS:[EBP+40B6A2]
006DE759    EB 06           JMP SHORT tElock_0.006DE761
006DE75B    039D 62D34000   ADD EBX,DWORD PTR SS:[EBP+40D362]          ;得到oep
。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。
006DE7AF    EB 02           JMP SHORT tElock_0.006DE7B3
006DE7B1    CD 20           INT 20
006DE7B3    61              POPAD
006DE7B4    FF6424 D0       JMP DWORD PTR SS:[ESP-30]                  ;跳往oep


脱壳思路:
由于在OEP dump  修复的时候  ImportREC跟踪3修复 总会假死 所以就没有在OEP处DUMP
纵观分析全过程  发现 在 处理完资源后  内存中已经有比较完整镜像  不幸的是 IAT已经被破坏了
所以 我们可以跳过  IAT的处理 这样 内存中就有正确的IAT结构了
006DE210    8B95 62D34000   MOV EDX,DWORD PTR SS:[EBP+40D362]        ;6decc0   imagebase = 400000 
006DE216    8BB5 52D34000   MOV ESI,DWORD PTR SS:[EBP+40D352]        ;6decb0   IatRva = 9a0000
006DE21C    85F6            TEST ESI,ESI
006DE21E    0F84 06040000   JE tElock_0.006DE62A
006DE224    03F2            ADD ESI,EDX                              ;IatVa = 49a0000
006DE226    83A5 52D44000 0>AND DWORD PTR SS:[EBP+40D452],0
006DE22D    8B46 0C         MOV EAX,DWORD PTR DS:[ESI+C]             ;IMAGE_IMPORT_DESCRIPTOR.Name1
006DE230    8366 0C 00      AND DWORD PTR DS:[ESI+C],0               ;破坏iat结构.Name1字段 (这里NOP掉)
006DE234    85C0            TEST EAX,EAX                             
006DE236    0F84 EE030000   JE tElock_0.006DE62A                     ;  (这里改JNE 跳走)

接下来
006DE65D    E8 13FAFFFF     CALL <tElock_0.uncompress>                            ;解压资源节
006DE662    83F8 FF         CMP EAX,-1                                            ;关键点(跳过iat后在此处dump) 
006DE665  ^ 0F84 10FCFFFF   JE <tElock_0.fail>

dump后 已经是正确的结构了 但是还需要 手动 修改下PE头里的
IAT的大小和RVA 以及OEP.  OEP就是靠定位前面的结构里的checksum1得到的
这样无需ImportREC就可以直接运行了
telock的2个结构  是靠在一起的  以4字节的0来间隔
它们的位置 相对于壳所在节的偏移为 0x1cb0

附件中的 样本 壳所在节基址是6dd0000那么 结构就在6decb0处(我试了2个样本 都能正确找到结构 所以姑且认为 偏移是固定的吧
万一找不到  就自己动手分析吧)
struct_telock_1未加密  struct_telock_2加密  dump的时候 查下结构 找到checksum1 取反就是OEP
样本的checksum1:006DECE0  FFF6B683
OEP就是FFF6B683取反9497c + 400000 = 49497c

至于脚本  RADASM里的脚本 很好用  就不把自己写的贴出来了



我发现 汉语真的很厉害  咱没有失业 只是待业