看雪CTF2019晋级赛Q2第六题《消失的岛屿》解题wp
程序的流程:![](data/attachment/album/201906/26/154519grkrar13i5jkvav6.png)
IDA伪代码:
```
int __cdecl main()
{
int v0; // eax@3
_BYTE v2; // @1
const char *v3; // @3
char *v4; // @3
__main();
printf("please enter Serial:");
scanf(" %s", v2);
if ( strlen(v2) > 0x31 )
puts("error");
v4 = (char *)calloc(1u, 0x400u);
v0 = strlen(v2);
base64_encode(v2, v4, v0);
v3 = "!NGV%,$h1f4S3%2P(hkQ94==";
if ( !strcmp("!NGV%,$h1f4S3%2P(hkQ94==", v4) )
puts("Success");
else
puts("Please Try Again");
free(v4);
system("pause");
return 0;
}
```
这里是程序的算法:
![](data/attachment/album/201906/26/154549m7t2b7npqjf1oqo2.png)
跟进去看看
![](data/attachment/album/201906/26/154559jgt3gcdil7tnycb7.png)
IDA伪代码:
```
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; // @2
uint8_t currenta; // @4
int j; // @1
int ja; // @2
int jb; // @4
int i; // @1
i = 0;
j = 0;
while ( i < binlength )
{
v3 = j;
ja = j + 1;
v4 = &base64;
*v4 = charEncrypt((bindata >> 2) & 0x3F);
current = 16 * bindata & 0x30;
if ( i + 1 >= binlength )
{
v5 = ja;
v6 = ja + 1;
v7 = &base64;
*v7 = charEncrypt(current);
base64 = '=';
v8 = v6 + 1;
j = v6 + 2;
base64 = '=';
break;
}
v9 = ja;
jb = ja + 1;
v10 = &base64;
*v10 = charEncrypt((bindata >> 4) | current);
currenta = 4 * bindata & 0x3C;
if ( i + 2 >= binlength )
{
base64 = charEncrypt(currenta);
v11 = jb + 1;
j = jb + 2;
base64 = '=';
break;
}
base64 = charEncrypt((bindata >> 6) | currenta);
v12 = jb + 1;
j = jb + 2;
v13 = &base64;
*v13 = charEncrypt(bindata & 0x3F);
i += 3;
}
base64 = 0;
return j;
}
```
这里看到base64必备的编码变换函数
![](data/attachment/album/201906/26/154648u7lvuuu50jsm1s71.png)
跟进去看看,找到字符表
![](data/attachment/album/201906/26/154710lh63mgtb5m2m9376.png)
OD定位,查看里面的存储数据,这里也能用IDA直接看,但是我还是习惯用OD来定位。
![](data/attachment/album/201906/26/154727fgxvvdixxqqudq1v.png)
到这里,就可以参考网上的base64,来写出对应的解密算法
```
int __cdecl base64_decode(char *base64, char *bindata, int binlength)
{
int t = 0, x = 0, y = 0, i = 0;
unsigned char c = 0;
int g = 3;
while (base64 != 0) {
// 需要解码的数据对应的ASCII值对应base64_suffix_map的值
c = charUnEncrypt(base64);
x++;
if (c == 255) return -1;// 对应的值不在转码表中
if (c == 253) continue;// 对应的值是换行或者回车
if (c == 254) { c = 0; g--; }// 对应的值是'='
t = (t << 6) | c; // 将其依次放入一个int型中占3字节
if (++y == 4) {
bindata = (unsigned char)((t >> 16) & 0xff);
if (g > 1) bindata = (unsigned char)((t >> 8) & 0xff);
if (g > 2) bindata = (unsigned char)(t & 0xff);
y = t = 0;
}
}
return i;
}
```
得出flag
![](data/attachment/album/201906/26/154806r00ereiee0evtm90.png)
程序解密完整源码如下:
```
#include "pch.h"
#include <iostream>
#include <locale>
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <string>
#include <windows.h>
char aTuvwxtulmnopqr = "tuvwxTUlmnopqrs7YZabcdefghij8yz0123456VWXkABCDEFGHIJKLMNOPQRS9+/";
char __cdecl charEncrypt(int data)
{
int dataa; //
dataa = aTuvwxtulmnopqr;
if (dataa > 64 && dataa <= 90)
return 155 - dataa;
if (dataa > 96 && dataa <= 122)
return dataa - 64;
if (dataa > 47 && dataa <= 57)
return dataa + 50;
if (dataa == 43)
return 119;
if (dataa == 47)
dataa = 121;
return dataa;
}
char __cdecl charUnEncrypt(int data)
{
int i;
if (data == 121) {
data = 47;
}
else if (data == 119) {
data = 43;
}
else if (data > 47 + 50 && data <= 57 + 50) {
data = data - 50;
}
else if (data > 96 - 64 && data <= 122 - 64) {
data = data + 64;
}
else if (data >= 155 - 90 && data < 155 - 64) {
data = 155 - data;
}
for (i = 0; i < 64; i++) {
if (data == aTuvwxtulmnopqr)
return i;
}
return 254;
}
int __cdecl base64_decode(char *base64, char *bindata, int binlength)
{
int t = 0, x = 0, y = 0, i = 0;
unsigned char c = 0;
int g = 3;
while (base64 != 0) {
// 需要解码的数据对应的ASCII值对应base64_suffix_map的值
c = charUnEncrypt(base64);
x++;
if (c == 255) return -1;// 对应的值不在转码表中
if (c == 253) continue;// 对应的值是换行或者回车
if (c == 254) { c = 0; g--; }// 对应的值是'='
t = (t << 6) | c; // 将其依次放入一个int型中占3字节
if (++y == 4) {
bindata = (unsigned char)((t >> 16) & 0xff);
if (g > 1) bindata = (unsigned char)((t >> 8) & 0xff);
if (g > 2) bindata = (unsigned char)(t & 0xff);
y = t = 0;
}
}
return i;
}
int __cdecl base64_encode(char *bindata, char *base64, int binlength)
{
int v3; // eax
char *v4; // ebx
int v5; // eax
int v6; // ST0C_4
char *v7; // ebx
int v8; // eax
int v9; // eax
char *v10; // ebx
int v11; // eax
int v12; // eax
char *v13; // ebx
uint8_t current; //
uint8_t currenta; //
int j; //
int ja; //
int jb; //
int i; //
i = 0;
j = 0;
while (i < binlength)
{
v3 = j;
ja = j + 1;
v4 = &base64;
*v4 = charEncrypt((bindata >> 2) & 0x3F);
current = (bindata << 4) & 0x30;
if (i + 1 >= binlength)
{
v5 = ja;
v6 = ja + 1;
v7 = &base64;
*v7 = charEncrypt(current);
base64 = '=';
v8 = v6 + 1;
j = v6 + 2;
base64 = '=';
break;
}
v9 = ja;
jb = ja + 1;
v10 = &base64;
*v10 = charEncrypt((bindata >> 4) | current);
currenta = 4 * bindata & 0x3C;
if (i + 2 >= binlength)
{
base64 = charEncrypt(currenta);
v11 = jb + 1;
j = jb + 2;
base64 = 61;
break;
}
base64 = charEncrypt((bindata >> 6) | currenta);
v12 = jb + 1;
j = jb + 2;
v13 = &base64;
*v13 = charEncrypt(bindata & 0x3F);
i += 3;
}
base64 = 0;
return j;
}
char * wchar2char(const wchar_t* wchar)//wchar转换为char
{
char * m_char;
int len = WideCharToMultiByte(CP_ACP, 0, wchar, wcslen(wchar), NULL, 0, NULL, NULL);
m_char = new char;
WideCharToMultiByte(CP_ACP, 0, wchar, wcslen(wchar), m_char, len, NULL, NULL);
m_char = '\0';
return m_char;
}
int main()
{
//goto lbtest;
int i = 0;
char buf = { 0 };
char buf1 = { 0 };
const wchar_t* code = L"!NGV%,$h1f4S3%2P(hkQ94==";
char* as = wchar2char(code);
//base64_encode(as, buf, 1);
base64_decode(as, buf1, 16);
printf(buf1);
}
```
题目:
页:
[1]