程序的流程:
IDA伪代码:
int __cdecl main()
{
int v0; // eax@3
_BYTE v2[3]; // [sp+11h] [bp-3Fh]@1
const char *v3; // [sp+48h] [bp-8h]@3
char *v4; // [sp+4Ch] [bp-4h]@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;
}
这里是程序的算法:
跟进去看看
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; // [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] = '=';
v8 = v6 + 1;
j = v6 + 2;
base64[v8] = '=';
break;
}
v9 = ja;
jb = ja + 1;
v10 = &base64[v9];
*v10 = charEncrypt((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] = '=';
break;
}
base64[jb] = charEncrypt((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;
}
这里看到base64必备的编码变换函数
跟进去看看,找到字符表
OD定位,查看里面的存储数据,这里也能用IDA直接看,但是我还是习惯用OD来定位。
到这里,就可以参考网上的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[x] != 0) {
// 需要解码的数据对应的ASCII值对应base64_suffix_map的值
c = charUnEncrypt(base64[x]);
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[i++] = (unsigned char)((t >> 16) & 0xff);
if (g > 1) bindata[i++] = (unsigned char)((t >> 8) & 0xff);
if (g > 2) bindata[i++] = (unsigned char)(t & 0xff);
y = t = 0;
}
}
return i;
}
得出flag
程序解密完整源码如下:
#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[65] = "tuvwxTUlmnopqrs7YZabcdefghij8yz0123456VWXkABCDEFGHIJKLMNOPQRS9+/";
char __cdecl charEncrypt(int data)
{
int dataa; // [esp+18h] [ebp+8h]
dataa = aTuvwxtulmnopqr[data];
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[i])
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[x] != 0) {
// 需要解码的数据对应的ASCII值对应base64_suffix_map的值
c = charUnEncrypt(base64[x]);
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[i++] = (unsigned char)((t >> 16) & 0xff);
if (g > 1) bindata[i++] = (unsigned char)((t >> 8) & 0xff);
if (g > 2) bindata[i++] = (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; // [esp+Bh] [ebp-Dh]
uint8_t currenta; // [esp+Bh] [ebp-Dh]
int j; // [esp+Ch] [ebp-Ch]
int ja; // [esp+Ch] [ebp-Ch]
int jb; // [esp+Ch] [ebp-Ch]
int i; // [esp+10h] [ebp-8h]
i = 0;
j = 0;
while (i < binlength)
{
v3 = j;
ja = j + 1;
v4 = &base64[v3];
*v4 = charEncrypt((bindata[i] >> 2) & 0x3F);
current = (bindata[i] << 4) & 0x30;
if (i + 1 >= binlength)
{
v5 = ja;
v6 = ja + 1;
v7 = &base64[v5];
*v7 = charEncrypt(current);
base64[v6] = '=';
v8 = v6 + 1;
j = v6 + 2;
base64[v8] = '=';
break;
}
v9 = ja;
jb = ja + 1;
v10 = &base64[v9];
*v10 = charEncrypt((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((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;
}
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[len + 1];
WideCharToMultiByte(CP_ACP, 0, wchar, wcslen(wchar), m_char, len, NULL, NULL);
m_char[len] = '\0';
return m_char;
}
int main()
{
//goto lbtest;
int i = 0;
char buf[256] = { 0 };
char buf1[256] = { 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);
}