首页
社区
课程
招聘
[分享]2021 MAR DASCTF RE题解
2021-4-7 08:58 4166

[分享]2021 MAR DASCTF RE题解

2021-4-7 08:58
4166

这次比赛, 没有向以前一样爆零了,就很舒服

 

赛后官方提供了复盘,就用 复盘一下,写一下wp

drinkSomeTea

 

主函数逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
int __cdecl main(int argc, const char **argv, const char **envp)
{
  HANDLE v3; // eax
  void *v4; // esi
  int result; // eax
  DWORD v6; // edi
  char *v7; // esi
  DWORD v8; // ebx
  HANDLE v9; // eax
  void *v10; // esi
  DWORD NumberOfBytesRead; // [esp+Ch] [ebp-8h] BYREF
  DWORD NumberOfBytesWritten; // [esp+10h] [ebp-4h] BYREF
 
  sub_401000();
  puts(aWelcomeToMyTea);
  v3 = CreateFileA(FileName, 0xC0000000, 0, 0, 3u, 0x80u, 0);
  v4 = v3;
  if ( v3 == (HANDLE)-1 )
  {
    puts(aIThinkYouDoNot);
    result = 0;
  }
  else
  {
    v6 = GetFileSize(v3, 0);
    if ( v6 < 0xEA60 )
    {
      SetFilePointer(v4, 0, 0, 0);
      NumberOfBytesRead = 0;
      ReadFile(v4, &unk_409988, v6, &NumberOfBytesRead, 0);
      CloseHandle(v4);
      if ( v6 >> 3 )
      {
        v7 = (char *)&unk_409988;
        v8 = v6 >> 3;
        do
        {
            //  关键函数,但是被 嵌入了花指令,  负责了关键部分数据处理
          ((void (__cdecl *)(char *, void *))loc_4010A0)(v7, &unk_407030);
          v7 += 8;
          --v8;
        }
        while ( v8 );
      }
      v9 = CreateFileA(aTeaPngOut, 0xC0000000, 0, 0, 2u, 0x80u, 0);
      v10 = v9;
      if ( v9 == (HANDLE)-1 )
      {
        puts(aIThinkYouDoNot);
      }
      else
      {
        NumberOfBytesWritten = 0;
        WriteFile(v9, &unk_409988, v6, &NumberOfBytesWritten, 0);
        CloseHandle(v10);
        puts(aNowThisCupOfTe);
      }
      result = 0;
    }
    else
    {
      puts(aYourTeaIsTooHo);
      result = 0;
    }
  }
  return result;
}

去花指令

 

 

明显的一个 tea 加密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int *__cdecl sub_4010A0(int *a1, _DWORD *a2)
{
  int *result; // eax
  int v3; // [esp+Ch] [ebp-14h]
  int i; // [esp+14h] [ebp-Ch]
  int v5; // [esp+18h] [ebp-8h]
  int v6; // [esp+1Ch] [ebp-4h]
 
  v5 = 0;
  v6 = a1[1];
  v3 = *a1;
  for ( i = 0; i < 32; ++i )
  {
    v5 -= 0x61C88647;
    v3 += (a2[1] + (v6 >> 5)) ^ (v5 + v6) ^ (*a2 + 16 * v6);
    v6 += (a2[3] + (v3 >> 5)) ^ (v5 + v3) ^ (a2[2] + 16 * v3);
  }
  a1[1] = v6;
  result = a1;
  *a1 = v3;
  return result;
}

密钥在main 函数里面
flag{fake_flag!}get out!

 

解密代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// tea加解密.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
 
#include <stdio.h>
 
 
void decrypt(unsigned int* v, unsigned int* key) {
    int l; // [esp+Ch] [ebp-14h]
    int sum; // [esp+18h] [ebp-8h]
    int r; // [esp+1Ch] [ebp-4h]
 
    r = v[1];
    l = v[0];
    sum = 0xC6EF3720;
    for (size_t i = 0; i < 32; i++) {
        //sum -= 0x61C88647;
        r -= (key[3] + (l >> 5)) ^ (sum + l) ^ (key[2] + (16 * l));
        l -= (key[1] + (r >> 5)) ^ (sum + r) ^ (key[0] + (16 * r));
        sum += 0x61C88647;
 
        //r -= ((l *16) + key[2]) ^ (l + sum) ^ ((l >> 5) + key[3]);
        //l -= ((r * 16) + key[0]) ^ (r + sum) ^ ((r >> 5) + key[1]);
    }
    v[0] = l;
    v[1] = r;
}
 
void de_file() {
    char file_path[] = { "C:\\Users\\Dell\\Desktop\\Test\\tea.png.out" };
 
    FILE* file_point = fopen(file_path, "rb");
    fseek(file_point, 0, SEEK_END);
    int len = ftell(file_point);
    fseek(file_point, 0, SEEK_SET);
    char* file_content = (char*)malloc(len);
    memset(file_content, 0,len);
 
    fread(file_content, 1, len, file_point);
 
    fclose(file_point);
 
    char new_file_path[] = { "C:\\Users\\Dell\\Desktop\\Test\\tea.png" };
 
    FILE* new_file_point = fopen(new_file_path, "wb");
    char secry_key[] = {
0x66, 0x6C, 0x61, 0x67, 0x7B, 0x66, 0x61, 0x6B, 0x65, 0x5F,
0x66, 0x6C, 0x61, 0x67, 0x21, 0x7D, 0x67, 0x65, 0x74, 0x20,
0x6F, 0x75, 0x74, 0x21, 0x20, 0x0A, 0x00
    };
 
    for (int i = 0; i < len; i += 8) {
        decrypt((unsigned int*)(file_content + i), (unsigned int*)secry_key);
    }
    fwrite(file_content, 1, len, new_file_point);
    fclose(new_file_point);
}
 
 
void main() {
 
    de_file();
}

有点坑, 当使用魔数 0x61C88647 时, 解密的初始化数值必须是 0xC6EF3720

 

flag

Enjoyit-1

 

de4dot 反混淆后,base64 变表解密,得到key, 再修改代码,输入key 即可得到flag

 

 

将所有等待时间删掉

 

flag

 

getflag

replace

是一个 hook ,将 IsDebugParent 执行流程替换, 再里面将 最后的比较进行了替换, 有一层很复杂的东西, 手撕不动(指我自己) , 哭了,我怎么这么菜

 

main 函数
代码简洁,易懂

 

最后替换的函数,也是解题的关键

 

参考这位师傅 replace 解法: https://www.cnblogs.com/c10udlnk/p/14606861.html
师傅们tql

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from binascii import *
from hashlib import md5
 
ans=unhexlify("416f6b116549435c2c0f1143174339023d4d4c0f183e7828")
tmps=[0,6,12,18]
seq=[]
 
 
for i in range(6):
    tmpl=[x+i for x in tmps]
    seq=seq+tmpl
 
print(seq)
arr1=[0 for i in range(24)]
for i in range(24):
    arr1[seq[i]]=ans[i]
 
box=[0x00000080, 0x00000065, 0x0000002F, 0x00000034, 0x00000012, 0x00000037, 0x0000007D, 0x00000040, 0x00000026, 0x00000016, 0x0000004B, 0x0000004D, 0x00000055, 0x00000043, 0x0000005C, 0x00000017, 0x0000003F, 0x00000069, 0x00000079, 0x00000053, 0x00000018, 0x00000002, 0x00000006, 0x00000061, 0x00000027, 0x00000008, 0x00000049, 0x0000004A, 0x00000064, 0x00000023, 0x00000056, 0x0000005B, 0x0000006F, 0x00000011, 0x0000004F, 0x00000014, 0x00000004, 0x0000001E, 0x0000005E, 0x0000002D, 0x0000002A, 0x00000032, 0x0000002B, 0x0000006C, 0x00000074, 0x00000009, 0x0000006E, 0x00000042, 0x00000070, 0x0000005A, 0x00000071, 0x0000001C, 0x0000007B, 0x0000002C, 0x00000075, 0x00000054, 0x00000030, 0x0000007E, 0x0000005F, 0x0000000E, 0x00000001, 0x00000046, 0x0000001D, 0x00000020, 0x0000003C, 0x00000066, 0x0000006B, 0x00000076, 0x00000063, 0x00000047, 0x0000006A, 0x00000029, 0x00000025, 0x0000004E, 0x00000031, 0x00000013, 0x00000050, 0x00000051, 0x00000033, 0x00000059, 0x0000001A, 0x0000005D, 0x00000044, 0x0000003E, 0x00000028, 0x0000000F, 0x00000019, 0x0000002E, 0x00000005, 0x00000062, 0x0000004C, 0x0000003A, 0x00000021, 0x00000045, 0x0000001F, 0x00000038, 0x0000007F, 0x00000057, 0x0000003D, 0x0000001B, 0x0000003B, 0x00000024, 0x00000041, 0x00000077, 0x0000006D, 0x0000007A, 0x00000052, 0x00000073, 0x00000007, 0x00000010, 0x00000035, 0x0000000A, 0x0000000D, 0x00000003, 0x0000000B, 0x00000048, 0x00000067, 0x00000015, 0x00000078, 0x0000000C, 0x00000060, 0x00000039, 0x00000036, 0x00000022, 0x0000007C, 0x00000058, 0x00000072, 0x00000068]
arr2=[0 for i in range(24)]
for i in range(5):
    for j in range(24):
        arr2[j]=box.index(arr1[j])
    arr1=arr2
myInput=''.join(map(chr,arr1))
print(myInput)
flag=myInput.encode()
print(md5(flag).hexdigest()) # 别忘了最后提交md5

变形栅栏 + 盒子变换

 

最后 md5 提交

 

这题,比赛的时候,上面的盒子变换都给我看傻了, 下面的栅栏直接给我干死,然后直接放弃这一题, 看师傅们随随便便解出来,我真的感觉自己是个废物

奇怪的扫雷

这题预期解是 开发扫雷外挂,并在几秒钟内解出来。 然后我也看不懂里面的代码,连异常咋触发的都看不懂, 哭了。靠着师傅们的wp, 勉强维持生活。

 

 

最后在出题人师傅不留余力的帮助下,完成了 扫雷外挂的开发, 太难了
about

 

使用工具:

  1. vs2019
  2. spy++
  3. ce

这里面出题人师傅关闭了 aslr , 所以基地址是直接固定的, 格子的大小是 16 * 16 ,sendmessage 点击是呈比例的, 和缩放与布局有关, 其他的也没啥, 具体参考:
https://www.xuenixiang.com/thread-2989-1-1.html

 

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// q师傅扫雷外挂开发.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
 
#include <iostream>
#include<Windows.h>
#include "assert.h"
 
 
#define MAPHEAD 0x0019627C
#define MAPHEIGHT 0x19623C
#define MAPWIDTH 0x196240
 
struct SigData {
    DWORD sate;
    DWORD flag;
}Pro;
 
 
int GetScaling() {
        // 获取窗口当前显示的监视器
        // 使用桌面的句柄.
        HWND hWnd = GetDesktopWindow();
        HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
 
        // 获取监视器逻辑宽度与高度
        MONITORINFOEX miex;
        miex.cbSize = sizeof(miex);
        GetMonitorInfo(hMonitor, &miex);
        int cxLogical = (miex.rcMonitor.right - miex.rcMonitor.left);
        int cyLogical = (miex.rcMonitor.bottom - miex.rcMonitor.top);
 
        // 获取监视器物理宽度与高度
        DEVMODE dm;
        dm.dmSize = sizeof(dm);
        dm.dmDriverExtra = 0;
        EnumDisplaySettings(miex.szDevice, ENUM_CURRENT_SETTINGS, &dm);
        int cxPhysical = dm.dmPelsWidth;
        int cyPhysical = dm.dmPelsHeight;
 
        // 缩放比例计算  实际上使用任何一个即可
        double horzScale = ((double)cxPhysical / (double)cxLogical);
        double vertScale = ((double)cyPhysical / (double)cyLogical);
        assert(horzScale == vertScale); // 宽或高这个缩放值应该是相等的
 
 
        return (int)round(16.0 / horzScale);
}
 
 
int main()
{
    int height = 0;
    int width = 0;
    DWORD MainPid = 0;
    HWND MainHwnd = FindWindow(NULL, TEXT("奇怪的扫雷"));
    GetWindowThreadProcessId(MainHwnd, &MainPid);
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, MainPid);
 
    SIZE_T size = 4;
    ReadProcessMemory(hProcess, (LPCVOID)MAPWIDTH, &width, 4, &size);
    ReadProcessMemory(hProcess, (LPCVOID)MAPHEIGHT, &height, 4, &size);
    int LeiCount = 0;
    LPCVOID tmp = NULL;
    SIZE_T ProSize = 8;
 
    int Scalie = GetScaling();
    for (int x = 1; x < height + 1; x++) {
        for (int y = 0; y < width; y++) {
            ReadProcessMemory(hProcess, (LPCVOID)(MAPHEAD + ((x - 1) * width + y) * 4), &tmp, 4, &size);
            ReadProcessMemory(hProcess, (LPCVOID)tmp, &Pro, 8, &ProSize);
 
            int xPos, yPos;
            xPos = (y * Scalie) + 26;
            yPos = (x * Scalie) + 46;
 
            if (Pro.flag == 0xffffffff) {
 
                SendMessage(MainHwnd, WM_RBUTTONDOWN, 0, MAKELPARAM(xPos, yPos));
                SendMessage(MainHwnd, WM_RBUTTONUP, 0, MAKELPARAM(xPos, yPos));
                printf("雷 ");
 
                LeiCount++;
            }
            else {
 
                SendMessage(MainHwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(xPos, yPos));
                SendMessage(MainHwnd, WM_LBUTTONUP, 0, MAKELPARAM(xPos, yPos));
 
 
                printf("无 ");
            }
        }
 
        printf("\n");
    }
 
    printf("\n有雷: %d 个, 高:%d, 宽: %d", LeiCount, height, width);
 
    return 1;
}

getflag


[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

收藏
点赞3
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回