首页
社区
课程
招聘
[原创]KCTF 2019 Q2 Writeup
2019-6-27 06:56 5315

[原创]KCTF 2019 Q2 Writeup

2019-6-27 06:56
5315

第四题:达芬奇密码

1、通过MessageBox提示字符串可以定位到关键代码,需要注意的是真正的校验代码是通过 0x00401F8A 处的指令    rep movsd  拷贝到0x4010E0的
.text:00401EEB 8D 85 F0 FC FF FF                       lea     eax, [ebp+String]
.text:00401EF1 50                                      push    eax             ; lpString
.text:00401EF2 68 E8 03 00 00                          push    3E8h            ; nIDDlgItem
.text:00401EF7 8B CE                                   mov     ecx, esi        ; this
.text:00401EF9 E8 17 75 00 00                          call    ?GetDlgItemTextW@CWnd@@QBEHHPA_WH@Z ; CWnd::GetDlgItemTextW(int,wchar_t *,int)
.text:00401EFE 8D 85 F0 FC FF FF                       lea     eax, [ebp+String]
.text:00401F04 8D 50 02                                lea     edx, [eax+2]
.text:00401F07
.text:00401F07                         loc_401F07:                             ; CODE XREF: onButtonCliked+70j
.text:00401F07 66 8B 08                                mov     cx, [eax]
.text:00401F0A 83 C0 02                                add     eax, 2
.text:00401F0D 66 85 C9                                test    cx, cx
.text:00401F10 75 F5                                   jnz     short loc_401F07
.text:00401F12 2B C2                                   sub     eax, edx
.text:00401F14 D1 F8                                   sar     eax, 1
.text:00401F16 83 F8 10                                cmp     eax, 10h
.text:00401F19 0F 85 BB 00 00 00                       jnz     loc_401FDA      ; 长度要等于0x10
.text:00401F1F 33 C0                                   xor     eax, eax
.text:00401F21
.text:00401F21                         loc_401F21:                             ; CODE XREF: onButtonCliked+A6j
.text:00401F21 B9 00 FF 00 00                          mov     ecx, 0FF00h
.text:00401F26 66 85 8C 45 F0 FC FF FF                 test    [ebp+eax*2+String], cx
.text:00401F2E 0F 85 A6 00 00 00                       jnz     loc_401FDA
.text:00401F34 8A 94 45 F0 FC FF FF                    mov     dl, byte ptr [ebp+eax*2+String]
.text:00401F3B 88 94 05 F0 FE FF FF                    mov     [ebp+eax+var_110], dl
.text:00401F42 40                                      inc     eax
.text:00401F43 83 F8 10                                cmp     eax, 10h
.text:00401F46 7C D9                                   jl      short loc_401F21
.text:00401F48 8B 1D 10 D2 51 00                       mov     ebx, ds:VirtualProtect
.text:00401F4E 8D 45 FC                                lea     eax, [ebp+flOldProtect]
.text:00401F51 50                                      push    eax             ; lpflOldProtect
.text:00401F52 6A 40                                   push    40h             ; flNewProtect
.text:00401F54 68 17 0D 00 00                          push    0D17h           ; dwSize
.text:00401F59 68 E0 10 40 00                          push    offset sub_4010E0 ; lpAddress
.text:00401F5E C7 45 F0 40 00 00 00                    mov     [ebp+var_10], 40h
.text:00401F65 C7 45 FC 00 00 00 00                    mov     [ebp+flOldProtect], 0
.text:00401F6C FF D3                                   call    ebx ; VirtualProtect
.text:00401F6E FF 15 08 D4 51 00                       call    ds:GetLastError
.text:00401F74 85 C0                                   test    eax, eax
.text:00401F76 75 62                                   jnz     short loc_401FDA
.text:00401F78 8B 55 FC                                mov     edx, [ebp+flOldProtect]
.text:00401F7B B9 CC 00 00 00                          mov     ecx, 0CCh
.text:00401F80 BE B8 47 56 00                          mov     esi, offset byte_5647B8
.text:00401F85 BF E0 10 40 00                          mov     edi, offset sub_4010E0
.text:00401F8A F3 A5                                   rep movsd                                           拷贝真正的校验代码到0x4010E0
.text:00401F8C 8D 4D F0                                lea     ecx, [ebp+var_10]
.text:00401F8F 51                                      push    ecx             ; lpflOldProtect
.text:00401F90 52                                      push    edx             ; flNewProtect
.text:00401F91 68 17 0D 00 00                          push    0D17h           ; dwSize
.text:00401F96 68 E0 10 40 00                          push    offset sub_4010E0 ; lpAddress
.text:00401F9B FF D3                                   call    ebx ; VirtualProtect
.text:00401F9D FF 15 08 D4 51 00                       call    ds:GetLastError
.text:00401FA3 85 C0                                   test    eax, eax
.text:00401FA5 75 30                                   jnz     short loc_401FD7
.text:00401FA7 89 45 F8                                mov     [ebp+var_8], eax
.text:00401FAA 8D 85 F0 FE FF FF                       lea     eax, [ebp+var_110]
.text:00401FB0 50                                      push    eax
.text:00401FB1 E8 2A F1 FF FF                          call    sub_4010E0                       进入校验
.text:00401FB6 89 45 F8                                mov     [ebp+var_8], eax
.text:00401FB9 83 7D F8 01                             cmp     [ebp+var_8], 1
.text:00401FBD 75 18                                   jnz     short loc_401FD7
.text:00401FBF 8B 4D F4                                mov     ecx, [ebp+var_C] ; this
.text:00401FC2 6A 00                                   push    0               ; unsigned int
.text:00401FC4 6A 00                                   push    0               ; lpCaption
.text:00401FC6 68 10 57 54 00                          push    offset Text     ; "Congratulations! You are right!"
.text:00401FCB E8 55 92 00 00                          call    ?MessageBoxW@CWnd@@QAEHPB_W0I@Z ; CWnd::MessageBoxW(wchar_t const *,wchar_t const *,uint)
.text:00401FD0 5F                                      pop     edi

2、校验代码还原
     1)、对16字节的序列号进行异或运算
char key[16] = { 0x16,0x96,0x8C,0xE3,0x81,0x98,0x6E,0x64,0x84,0x08,0xDC,0x81,0xBE,0x4D,0x48,0x4F };

char* xorSerial(char serial[16])
{
	char *resultSerial = new char[16];

	for (int i = 0; i < 8; i++)
	{
		resultSerial[i] = key[i] ^ serial[i];
		resultSerial[i + 8] = key[i + 8] ^ serial[i + 8];
	}

	return resultSerial;
}

     2)、对异或后的结果进行检查:第7和第15字节不能为0,且第7字节的高4位必须为0
bool check(char *serial)
{
	if (serial[7] == 0 || serial[15] == 0)
	{
		return false;
	}

	if (serial[7] & 0xF0)
	{
		return false;
	}

	return true;
}

       3)、把序列号拆成两段,前8个字节为第一段设为x,后8个字节为第二段设为y;最后可得方程:x^2 - 7y^2 = 8

               不过最后不会解这个方程

第六题:消失的岛屿


1、随便输入一个字符串提示:“Please Try Again”,通过字符串搜索找到关键代码
.text:00401622 ; int __cdecl main(int argc, char **argv)
.text:00401622                 public _main
.text:00401622 _main           proc near               ; CODE XREF: ___mingw_CRTStartup+F8p
.text:00401622
.text:00401622 argc            = dword ptr  8
.text:00401622 argv            = dword ptr  0Ch
.text:00401622
.text:00401622                 push    ebp
.text:00401623                 mov     ebp, esp
.text:00401625                 and     esp, 0FFFFFFF0h
.text:00401628                 sub     esp, 50h
.text:0040162B                 call    ___main
.text:00401630                 mov     dword ptr [esp], offset aPleaseEnterSer ; "please enter Serial:"
.text:00401637                 call    _printf
.text:0040163C                 lea     eax, [esp+11h]
.text:00401640                 mov     [esp+4], eax
.text:00401644                 mov     dword ptr [esp], offset aS ; " %s"
.text:0040164B                 call    _scanf                                                   读取输入的字符串
.text:00401650                 lea     eax, [esp+11h]
.text:00401654                 mov     [esp], eax      ; char *
.text:00401657                 call    _strlen
.text:0040165C                 cmp     eax, 31h
.text:0040165F                 jbe     short loc_40166D                                
.text:00401661                 mov     dword ptr [esp], offset aError ; "error"          字符串长度大于0x31,则错误
.text:00401668                 call    _puts
.text:0040166D
.text:0040166D loc_40166D:                             ; CODE XREF: _main+3Dj
.text:0040166D                 mov     dword ptr [esp+4], 400h ; size_t
.text:00401675                 mov     dword ptr [esp], 1 ; size_t
.text:0040167C                 call    _calloc
.text:00401681                 mov     [esp+4Ch], eax
.text:00401685                 lea     eax, [esp+11h]
.text:00401689                 mov     [esp], eax      ; char *
.text:0040168C                 call    _strlen
.text:00401691                 mov     [esp+8], eax    ; binlength
.text:00401695                 mov     eax, [esp+4Ch]
.text:00401699                 mov     [esp+4], eax    ; base64
.text:0040169D                 lea     eax, [esp+11h]
.text:004016A1                 mov     [esp], eax      ; bindata
.text:004016A4                 call    _base64_encode                                         字符串进行base64编码
.text:004016A9                 mov     dword ptr [esp+48h], offset aNgvH1f4s32pHkq ; "!NGV%,$h1f4S3%2P(hkQ94=="
.text:004016B1                 mov     eax, [esp+4Ch]
.text:004016B5                 mov     [esp+4], eax    ; char *
.text:004016B9                 mov     eax, [esp+48h]
.text:004016BD                 mov     [esp], eax      ; char *
.text:004016C0                 call    _strcmp                               编码后的base字符串与!NGV%,$h1f4S3%2P(hkQ94==比较,相等则成功                         
.text:004016C5                 test    eax, eax
.text:004016C7                 jnz     short loc_4016D7
.text:004016C9                 mov     dword ptr [esp], offset aSuccess ; "Success"
.text:004016D0                 call    _puts
.text:004016D5                 jmp     short loc_4016E3
.text:004016D7 ; ---------------------------------------------------------------------------
.text:004016D7
.text:004016D7 loc_4016D7:                             ; CODE XREF: _main+A5j
.text:004016D7                 mov     dword ptr [esp], offset aPleaseTryAgain ; "Please Try Again"
.text:004016DE                 call    _puts
.text:004016E3
.text:004016E3 loc_4016E3:                             ; CODE XREF: _main+B3j
.text:004016E3                 mov     eax, [esp+4Ch]
.text:004016E7                 mov     [esp], eax      ; void *
.text:004016EA                 call    _free
.text:004016EF                 mov     dword ptr [esp], offset aPause ; "pause"
.text:004016F6                 call    _system
.text:004016FB                 mov     eax, 0
.text:00401700                 leave
.text:00401701                 retn


2、还原base64编码代码,编码方法
int __cdecl base64_encode(const uint8_t *bindata, char *base64, int binlength)
{
  int v3; // eax@2
  char *v4; // ebx@2
  int v5; // eax@3
  int v6; // ST0C_4@3
  char *v7; // ebx@3
  int v8; // eax@3
  int v9; // eax@4
  char *v10; // ebx@4
  int v11; // eax@5
  int v12; // eax@6
  char *v13; // ebx@6
  uint8_t current; // [sp+Bh] [bp-Dh]@2
  uint8_t currenta; // [sp+Bh] [bp-Dh]@4
  int j; // [sp+Ch] [bp-Ch]@1
  int ja; // [sp+Ch] [bp-Ch]@2
  int jb; // [sp+Ch] [bp-Ch]@4
  int i; // [sp+10h] [bp-8h]@1

  i = 0;
  j = 0;
  while ( i < binlength )
  {
    v3 = j;
    ja = j + 1;
    v4 = &base64[v3];
    *v4 = charEncrypt((bindata[i] >> 2) & 0x3F);
    current = 16 * bindata[i] & 0x30;
    if ( i + 1 >= binlength )
    {
      v5 = ja;
      v6 = ja + 1;
      v7 = &base64[v5];
      *v7 = charEncrypt(current);
      base64[v6] = 61;
      v8 = v6 + 1;
      j = v6 + 2;
      base64[v8] = 61;
      break;
    }
    v9 = ja;
    jb = ja + 1;
    v10 = &base64[v9];
    *v10 = charEncrypt((unsigned __int8)((bindata[i + 1] >> 4) | current));
    currenta = 4 * bindata[i + 1] & 0x3C;
    if ( i + 2 >= binlength )
    {
      base64[jb] = charEncrypt(currenta);
      v11 = jb + 1;
      j = jb + 2;
      base64[v11] = 61;
      break;
    }
    base64[jb] = charEncrypt((unsigned __int8)((bindata[i + 2] >> 6) | currenta));
    v12 = jb + 1;
    j = jb + 2;
    v13 = &base64[v12];
    *v13 = charEncrypt(bindata[i + 2] & 0x3F);
    i += 3;
  }
  base64[j] = 0;
  return j;
}


charEncrypt() 方法还原
unsigned char aTuvwxtulmnopqf[] = { 't','u','v','w','x','T','U','l','m','n','o','p','q','r','s',
'7','Y','Z','a','b','c','d','e','f','g','h','i','j','8','y','z','0','1','2','3','4','5','6',
'V','W','X','k','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','9','+','/' };

int charEncrypt(int data)
{
	int result;
	int dataa;

	dataa = aTuvwxtulmnopqf[data];
	if (dataa <= 64 || dataa > 90)
	{
		if (dataa <= 96 || dataa > 122)
		{
			if (dataa <= 47 || dataa > 57)
			{
				if (dataa == 43)
				{
					result = 119;
				}
				else
				{
					if (dataa == 47)
					{
						dataa = 121;
					}

					result = dataa;
				}
			}
			else
			{
				result = dataa + 50;
			}
		}
		else
		{
			result = dataa - 64;
		}
	}
	else
	{
		result = 155 - dataa;
	}

	return result;
}

最后经过反推获得flag

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

最后于 2019-6-28 11:25 被kanxue编辑 ,原因:
收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回