吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6565|回复: 37
收起左侧

[原创] 2020西湖论剑 re-loader

  [复制链接]
三年三班三井寿 发表于 2020-10-10 17:09
本帖最后由 三年三班三井寿 于 2020-10-10 17:15 编辑

挺久不碰win了,最近西湖论剑,晚上下班就随便看了看re的题。
这一题在re中应该算比较简单的,共三个文件loader.exe,code还有一个脚本启动器getflag.bat。
直接运行exe闪退,脚本有混淆,但也很容易去除。
E(WJ$UR3(JNTUK0_CBISAMR.png
去除混淆后脚本为:

@set @=
@set ;=
@set a=
@set b=
@set }=
@set c=
@set d=
@set ,=
@set e=
@set f=
@set g=
@set !=
@set h=
@set i=
@set j=
@set '=
@set k=
@set l=
@set m=
@set #=
@set n=
@set o=
@set )=
@set p=
@set q=
@set r=
@set _=
@set s=
@set t=
@set u=
@set (=
@set v=
@set $=
@set w=
@set x=
@set y=
@set {=
@set z=
@echo off
echo Your Password:
loader.exe code -d 114514
pause

前面一堆混淆的参数,有用的就是loader.exe code -d 114514。接着按着脚本设定的参数调试loader.exe即可。
loader实际上也就是对code解密加载,

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int i_114514; // eax

  sub_402870();
  if ( argc <= 2 )
  {
    sub_408310("Error\n");
    exit(0);
  }
  if ( *argv[2] == 0x2D && argv[2][1] == 0x64 ) // -d
    byte_40B068 = 1;
  if ( byte_40B068 )
  {
    if ( argc <= 2 )
    {
      sub_408310("Error\n");
      exit(0);
    }
    i_114514 = atoi(argv[3]);
    sub_4017B0((char *)argv[1], i_114514);
    sub_401A6E(TempFileName);
  }
  sub_401A6E((char *)argv[1]);
}

在sub_4017B0中会从code中解密生成一个临时文件,code前8字节作为CRC校验值,以及解密的长度。之后在sub_401A6E中申请空间填入代码。这些以及填入的逻辑等等其实对于题目本身而言并不重要。
跟踪到输入验证部分,直接dump出代码即可。但我直接在od上没能dump下来,题目也比较简单,直接撸汇编也不需要什么时间:

00ADD420    55              PUSH EBP
00ADD421    8BEC            MOV EBP,ESP
00ADD423    81EC D8000000   SUB ESP,0xD8
00ADD429    53              PUSH EBX
00ADD42A    56              PUSH ESI
00ADD42B    57              PUSH EDI
00ADD42C    8DBD 28FFFFFF   LEA EDI,DWORD PTR SS:[EBP-0xD8]
00ADD432    B9 36000000     MOV ECX,0x36
00ADD437    B8 CCCCCCCC     MOV EAX,0xCCCCCCCC
00ADD43C    F3:AB           REP STOS DWORD PTR ES:[EDI]
00ADD43E    B9 2BC0BB00     MOV ECX,0xBBC02B
00ADD443    E8 14AFFFFF     CALL 00AD835C
00ADD448    6A 28           PUSH 0x28
00ADD44A    68 888EBB00     PUSH 0xBB8E88
00ADD44F    68 700EB900     PUSH 0xB90E70                            ; ASCII "%s"
00ADD454    E8 C1A0FFFF     CALL <scanf>                             ; scanf
00ADD459    83C4 0C         ADD ESP,0xC
00ADD45C    68 888EBB00     PUSH 0xBB8E88
00ADD461    E8 1D92FFFF     CALL <strlen>
00ADD466    83C4 04         ADD ESP,0x4
00ADD469    83F8 20         CMP EAX,0x20
00ADD46C    74 14           JE SHORT 00ADD482
00ADD46E    68 740EB900     PUSH 0xB90E74                            ; len(str)!=0x20,fail
00ADD473    E8 2690FFFF     CALL 00AD649E
00ADD478    83C4 04         ADD ESP,0x4
00ADD47B    33C0            XOR EAX,EAX
00ADD47D    E9 AD000000     JMP 00ADD52F
00ADD482    C745 F8 0000000>MOV DWORD PTR SS:[EBP-0x8],0x0           ; i=0
00ADD489    EB 09           JMP SHORT 00ADD494
00ADD48B    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-0x8]
00ADD48E    83C0 01         ADD EAX,0x1
00ADD491    8945 F8         MOV DWORD PTR SS:[EBP-0x8],EAX
00ADD494    837D F8 20      CMP DWORD PTR SS:[EBP-0x8],0x20
00ADD498    7D 3B           JGE SHORT 00ADD4D5                       ; for(i=0;i<0x20;i++)
00ADD49A    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-0x8]
00ADD49D    0FB688 888EBB00 MOVZX ECX,BYTE PTR DS:[EAX+0xBB8E88]     ; ecx=str[i]
00ADD4A4    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-0x8]
00ADD4A7    99              CDQ
00ADD4A8    BE 06000000     MOV ESI,0x6
00ADD4AD    F7FE            IDIV ESI                                 ; edx=i%6
00ADD4AF    0FBE92 2080BB00 MOVSX EDX,BYTE PTR DS:[EDX+0xBB8020]     ; edx=str_PEFile[i%6]
00ADD4B6    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-0x8]
00ADD4B9    0D E3000000     OR EAX,0xE3                              ; i | 0xE3
00ADD4BE    03D0            ADD EDX,EAX                              ; edx=str_PEFile[i%6]+(i | 0xE3)
00ADD4C0    8B45 F8         MOV EAX,DWORD PTR SS:[EBP-0x8]
00ADD4C3    C1E0 04         SHL EAX,0x4                              ; eax=i<<4
00ADD4C6    33D0            XOR EDX,EAX                              ; edx=(str_PEFile[i%6]+(i | 0xE3))^(i<<4)
00ADD4C8    33CA            XOR ECX,EDX
00ADD4CA    8B55 F8         MOV EDX,DWORD PTR SS:[EBP-0x8]
00ADD4CD    888A 888EBB00   MOV BYTE PTR DS:[EDX+0xBB8E88],CL        ; str[i]^=edx
00ADD4D3  ^ EB B6           JMP SHORT 00ADD48B
00ADD4D5    C745 EC 0000000>MOV DWORD PTR SS:[EBP-0x14],0x0          ; j=0
00ADD4DC    EB 09           JMP SHORT 00ADD4E7
00ADD4DE    8B45 EC         MOV EAX,DWORD PTR SS:[EBP-0x14]
00ADD4E1    83C0 01         ADD EAX,0x1
00ADD4E4    8945 EC         MOV DWORD PTR SS:[EBP-0x14],EAX
00ADD4E7    837D EC 20      CMP DWORD PTR SS:[EBP-0x14],0x20
00ADD4EB    7D 2E           JGE SHORT 00ADD51B                       ; for(j=0;j<0x20;j++)
00ADD4ED    8B45 EC         MOV EAX,DWORD PTR SS:[EBP-0x14]
00ADD4F0    0FB688 888EBB00 MOVZX ECX,BYTE PTR DS:[EAX+0xBB8E88]     ; ecx=str[i]
00ADD4F7    8B55 EC         MOV EDX,DWORD PTR SS:[EBP-0x14]
00ADD4FA    0FB682 2880BB00 MOVZX EAX,BYTE PTR DS:[EDX+0xBB8028]     ; eax=arr2[i]
00ADD501    3BC8            CMP ECX,EAX                              ; str[i]==arr2[i]
00ADD503    74 14           JE SHORT 00ADD519
00ADD505    68 740EB900     PUSH 0xB90E74                            ; ASCII "Fail\n"
00ADD50A    E8 8F8FFFFF     CALL 00AD649E
00ADD50F    83C4 04         ADD ESP,0x4
00ADD512    6A 00           PUSH 0x0
00ADD514    E8 2AB3FFFF     CALL 00AD8843
00ADD519  ^ EB C3           JMP SHORT 00ADD4DE
00ADD51B    68 7C0EB900     PUSH 0xB90E7C                            ; ASCII "Win!\n"
00ADD520    E8 798FFFFF     CALL 00AD649E
00ADD525    83C4 04         ADD ESP,0x4
00ADD528    6A 00           PUSH 0x0
00ADD52A    E8 14B3FFFF     CALL 00AD8843
00ADD52F    5F              POP EDI
00ADD530    5E              POP ESI
00ADD531    5B              POP EBX
00ADD532    81C4 D8000000   ADD ESP,0xD8
00ADD538    3BEC            CMP EBP,ESP
00ADD53A    E8 EAAEFFFF     CALL 00AD8429
00ADD53F    8BE5            MOV ESP,EBP
00ADD541    5D              POP EBP
00ADD542    C3              RETN

首先就是对输入的长度限定为0x20,接着按字节将输入的字符串与"PEFile"计算异或。

最后再将异或后的字符串与另一组值比较即可。

通过输出也就能直接计算得到输入了:

  BYTE str_PEFile[] = { 0x50, 0x45, 0x46, 0x69, 0x6c, 0x65 };
        BYTE output[] = {
                0x02, 0x0d, 0x6a, 0x1a, 0x27, 0x7f, 0x32, 0x65, 0x86, 0xa5, 0xc5, 0xd7, 0xcf, 0xdd, 0xe3, 0x98,
                0x3d, 0x79, 0x53, 0x6a, 0x18, 0x54, 0x37, 0x14, 0xa9, 0xe0, 0x82, 0xb2, 0xce, 0x80, 0xcd, 0x8c
        };
        for (int i = 0; i < 0x20; ++i) {
                output[i] ^= (str_PEFile[i % 6] + (i | 0xE3)) ^ (i << 4);
        }

_@D4U%7RMB{%[I]C7%`M8RC.png

免费评分

参与人数 5威望 +1 吾爱币 +24 热心值 +5 收起 理由
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
班长的男人 + 1 + 1 谢谢@Thanks!
Wolfei + 1 + 1 谢谢@Thanks!
0615 + 1 + 1 我很赞同!
re1wn + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

re1wn 发表于 2020-10-10 22:11
|矢空 发表于 2020-10-10 19:01
能具体说一下是怎么去混淆的吗

我不会去混淆,我就先让程序跑起来,再用x32dbg附加这个进程,输入字符后跟着往里走(有查断点的反调试,设置新运行点即可跳过),直到找到fail和win的字符串,选中整个主函数,右键snowman反编译,逻辑清晰,一较复杂的异或和最后的明文比较

QQ截图20201010215959.png

tmp=[0x02,0x0D,0x6A,0x1A,0x27,0x7F,0x32,0x65,0x86,0xA5,0xC5,0xD7,0xCF,0xDD,0xE3,0x98,0x3D,0x79,0x53,0x6A,0x18,0x54,0x37,0x14,0xA9,0xE0,0x82,0xB2,0xCE,0x80,0xCD,0x8C]
stri='PEFile' 
flag=[0 for i in range(0x20)]
for i in range(0x20):
    flag[i]=(tmp[i]^(ord(stri[i%6])+(i|0xe3)^i<<4))&0xff
print(flag)
print(''.join(map(chr,flag)))
#15cf4ce97a270960b10bed48b0cfe4b8

免费评分

参与人数 2吾爱币 +8 热心值 +2 收起 理由
Hmily + 7 + 1 用心讨论,共获提升!
|矢空 + 1 + 1 我很赞同!

查看全部评分

andytong123 发表于 2020-10-10 19:22
jige123 发表于 2020-10-10 17:21
凌云科技 发表于 2020-10-10 17:22
膜拜大佬看不懂啊
MrKang 发表于 2020-10-10 17:37
感觉这些对于楼主就是小菜一碟
whatcos 发表于 2020-10-10 17:45
大佬,我实话告诉你吧,我看不懂
wysyz 发表于 2020-10-10 18:31
大佬,我实话告诉你吧,我看不懂
|矢空 发表于 2020-10-10 19:01
能具体说一下是怎么去混淆的吗
re1wn 发表于 2020-10-10 19:10
师傅,脚本启动器的混淆代码如何去除?
|矢空 发表于 2020-10-10 19:12
re1wn 发表于 2020-10-10 19:10
师傅,脚本启动器的混淆代码如何去除?

我试了下,用火绒剑可以提取CMD内的字符串ode -d 114514,但不能完整恢复
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 17:50

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表