[Revserse][BJDCTF2020]encode

[BJDCTF2022]encode(点击下载)

分析

文件带有upx壳,脱壳之后,进入ida分析
根据字符串里面的right字符找到窗口

file

文件将输入点放在v6数组的第50个地址上面,输入之后判断长度为21.
然后文件进入了sub_8048AC2进行了加密

int __cdecl sub_8048AC2(int a1)
{
  int v2; // [esp+8h] [ebp-20h]
  int v3; // [esp+Ch] [ebp-1Ch]
  int v4; // [esp+10h] [ebp-18h]
  int v5; // [esp+18h] [ebp-10h]
  int v6; // [esp+1Ch] [ebp-Ch]

  v5 = sub_805BBD0(a1);
  if ( v5 % 3 )
    v2 = 4 * (v5 / 3 + 1);
  else
    v2 = 4 * (v5 / 3);
  v6 = sub_80597A0(v2 + 1);
  *(_BYTE *)(v2 + v6) = 0;
  v3 = 0;
  v4 = 0;
  while ( v2 - 2 > v3 )
  {
    *(_BYTE *)(v6 + v3) = a0123456789Abcd[*(_BYTE *)(v4 + a1) >> 2];
    *(_BYTE *)(v6 + v3 + 1) = a0123456789Abcd[(16 * (*(_BYTE *)(v4 + a1) & 3)) | (*(_BYTE *)(v4 + 1 + a1) >> 4)];
    *(_BYTE *)(v6 + v3 + 2) = a0123456789Abcd[(4 * (*(_BYTE *)(v4 + 1 + a1) & 0xF)) | (*(_BYTE *)(v4 + 2 + a1) >> 6)];
    *(_BYTE *)(v6 + v3 + 3) = a0123456789Abcd[*(_BYTE *)(v4 + 2 + a1) & 0x3F];
    v4 += 3;
    v3 += 4;
  }
  if ( v5 % 3 == 1 )
  {
    *(_BYTE *)(v3 - 2 + v6) = 61;
    *(_BYTE *)(v3 - 1 + v6) = 61;
  }
  else if ( v5 % 3 == 2 )
  {
    *(_BYTE *)(v3 - 1 + v6) = 61;
  }
  return v6;
}

根据逻辑发现是Base64
密码表为:

0123456789+/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ

sub_80481D0是将base64加密后的数据存到v5 + 18 的地址上面
再使用for循环和v5这串密钥循环异或
最后进入sub_8048E24

unsigned int __cdecl sub_8048E24(int a1, unsigned int a2, int a3, int a4)
{
  unsigned int result; // eax
  char v5; // [esp+1Bh] [ebp-11Dh]
  int v6; // [esp+1Ch] [ebp-11Ch]
  int v7; // [esp+20h] [ebp-118h]
  unsigned int i; // [esp+24h] [ebp-114h]
  char v9[256]; // [esp+2Ch] [ebp-10Ch] BYREF
  unsigned int v10; // [esp+12Ch] [ebp-Ch]

  v10 = __readgsdword(0x14u);
  sub_8048CC2(v9, a3, a4);
  LOBYTE(v6) = 0;
  LOBYTE(v7) = 0;
  for ( i = 0; i < a2; ++i )
  {
    v6 = (unsigned __int8)(v6 + 1);
    v7 = (unsigned __int8)(v9[v6] + v7);
    v5 = v9[v6];
    v9[v6] = v9[v7];
    v9[v7] = v5;
    *(_BYTE *)(a1 + i) ^= v9[(unsigned __int8)(v9[v6] + v9[v7])];
  }
  result = __readgsdword(0x14u) ^ v10;
  if ( result )
    sub_806FA00();
  return result;
}

其中调用了 sub_8048CC2(v9, a3, a4);

unsigned int __cdecl sub_8048CC2(int a1, int a2, unsigned int a3)
{
  unsigned int result; // eax
  char v4; // [esp+13h] [ebp-115h]
  int i; // [esp+14h] [ebp-114h]
  int j; // [esp+14h] [ebp-114h]
  int v7; // [esp+18h] [ebp-110h]
  char v8[256]; // [esp+1Ch] [ebp-10Ch]
  unsigned int v9; // [esp+11Ch] [ebp-Ch]

  v9 = __readgsdword(0x14u);
  for ( i = 0; i <= 255; ++i )
  {
    *(_BYTE *)(i + a1) = i;
    v8[i] = *(_BYTE *)(i % a3 + a2);
  }
  v7 = 0;
  for ( j = 0; j <= 255; ++j )
  {
    v7 = (*(unsigned __int8 *)(j + a1) + v7 + (unsigned __int8)v8[j]) % 256;
    v4 = *(_BYTE *)(j + a1);
    *(_BYTE *)(a1 + j) = *(_BYTE *)(v7 + a1);
    *(_BYTE *)(a1 + v7) = v4;
  }
  result = __readgsdword(0x14u) ^ v9;
  if ( result )
    sub_806FA00();
  return result;
}

分析之后发现是rc4加密。

题解:

首先将v6地址上存储的数据进行rc4解密,然后循环异或,最后再使用base64变表解密,就行了。
【注意】
题目中这个v6的字符串,由于ida的原因是分析错误了的。
所以我们需要手动改造一下,我们可以发现这一段语句

if ( sub_805BBD0(&v6[50]) == 21 )
    sub_804EAF0(0);

动态调试后发现这个sub_805BBD0是一个获取字符串长的的语句
那么flag长度是21的话,经过base64加密之后应该是28位数,但是v6中存储的却只有49位数字,这是因为这个字符串有些01或者0E被识别成了1和E
正确的enc:

int a[]={
    0xE8,0xD8,0xBD,0x91,0x87,0x1A,0x01,0x0E,0x56,0x0F
    ,0x53,0xF4,0x88,0x96,0x82,0xF9,0x61,0x42,0x0A,0xF2,0xAB
    ,0x08,0xFE,0xD7,0xAC,0xFD,0x5E,0x00
};

EXP

直接手撸代码版本

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<string>
#include<cstring>
#include<list>
#include<stdlib.h>
#include<windows.h>
#include<iostream>
#include<cstring>
#include<bitset>
#include<vector>
#include<stdlib.h>
#include<time.h>
#include<sstream>
#include<cstring>
/*base64.c*/  
#include "base64.h"  
using namespace std;
    //base64.c
#include"base64.h"
char base64char[] = "0123456789+/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
char c;
char* base64_encode(char* binData, char* base64, int binLength)
{
    int i = 0;
    int j = 0;
    int current = 0;
    for (i = 0; i < binLength; i += 3) {
        //获取第一个6位
        current = (*(binData + i) >> 2) & 0x3F;
        *(base64 + j++) = base64char[current];
        //获取第二个6位的前两位
        current = (*(binData + i) << 4) & 0x30;
        //如果只有一个字符,那么需要做特殊处理
        if (binLength <= (i + 1)) {
            *(base64 + j++) = base64char[current];
            *(base64 + j++) = '=';
            *(base64 + j++) = '=';
            break;
        }
        //获取第二个6位的后四位
        current |= (*(binData + i + 1) >> 4) & 0xf;
        *(base64 + j++) = base64char[current];
        //获取第三个6位的前四位
        current = (*(binData + i + 1) << 2) & 0x3c;
        if (binLength <= (i + 2)) {
            *(base64 + j++) = base64char[current];
            *(base64 + j++) = '=';
            break;
        }
        //获取第三个6位的后两位
        current |= (*(binData + i + 2) >> 6) & 0x03;
        *(base64 + j++) = base64char[current];
        //获取第四个6位
        current = *(binData + i + 2) & 0x3F;
        *(base64 + j++) = base64char[current];
    }
    *(base64 + j) = '\0';
    return base64;
}

char* base64_decode(char const* base64Str, char* debase64Str, int encodeStrLen)
{
    int i = 0;
    int j = 0;
    int k = 0;
    char temp[4] = "";

    for (i = 0; i < encodeStrLen; i += 4) {
        for (j = 0; j < 64; j++) {
            if (*(base64Str + i) == base64char[j]) {
                temp[0] = j;
            }
        }

        for (j = 0; j < 64; j++) {
            if (*(base64Str + i + 1) == base64char[j]) {
                temp[1] = j;
            }
        }

        for (j = 0; j < 64; j++) {
            if (*(base64Str + i + 2) == base64char[j]) {
                temp[2] = j;
            }
        }

        for (j = 0; j < 64; j++) {
            if (*(base64Str + i + 3) == base64char[j]) {
                temp[3] = j;
            }
        }

        *(debase64Str + k++) = ((temp[0] << 2) & 0xFC) | ((temp[1] >> 4) & 0x03);
        if (*(base64Str + i + 2) == '=')
            break;

        *(debase64Str + k++) = ((temp[1] << 4) & 0xF0) | ((temp[2] >> 2) & 0x0F);
        if (*(base64Str + i + 3) == '=')
            break;

        *(debase64Str + k++) = ((temp[2] << 6) & 0xF0) | (temp[3] & 0x3F);
    }
    return debase64Str;
}

unsigned int __cdecl sub_8048CC2(unsigned __int8 * a1, char *a2, unsigned int a3)
{
  char v4; // [esp+13h] [ebp-115h]
  int i; // [esp+14h] [ebp-114h]
  int j; // [esp+14h] [ebp-114h]
  int v7; // [esp+18h] [ebp-110h]
  unsigned __int8  v8[256]; // [esp+1Ch] [ebp-10Ch]

  for ( i = 0; i <= 255; ++i )
  {
    *(i + a1) = i;
    v8[i] = *(i % a3 + a2);
  }
  v7 = 0;
  for ( j = 0; j <= 255; ++j )
  {
    v7 = (*(unsigned __int8 *)(j + a1) + v7 + (unsigned __int8)v8[j]) % 256;
    v4 = *(j + a1);
    *(a1 + j) = *(v7 + a1);
    *(a1 + v7) = v4;
  }
  return 0;
}

unsigned int __cdecl sub_8048E24(int* a1, unsigned int a2, char * a3, unsigned int a4)
{
  char v5; // [esp+1Bh] [ebp-11Dh]
  int v6; // [esp+1Ch] [ebp-11Ch]
  int v7; // [esp+20h] [ebp-118h]
  unsigned int i; // [esp+24h] [ebp-114h]
  unsigned __int8 v9[256]; // [esp+2Ch] [ebp-10Ch] BYREF // [esp+12Ch] [ebp-Ch]

  sub_8048CC2(v9, a3, a4);
  v6 = 0;
  v7 = 0;
  for ( i = 0; i < a2; ++i )
  {
    v6 = (unsigned __int8)(v6 + 1);
    v7 = (unsigned __int8)(v9[v6] + v7);
    v5 = v9[v6];
    v9[v6] = v9[v7];
    v9[v7] = v5;
    *(a1 + i) ^= v9[(unsigned __int8)(v9[v6] + v9[v7])];
  }
  return 0;
}
int a[]={
    0xE8,0xD8,0xBD,0x91,0x87,0x1A,0x01,0x0E,0x56,0x0F
    ,0x53,0xF4,0x88,0x96,0x82,0xF9,0x61,0x42,0x0A,0xF2,0xAB
    ,0x08,0xFE,0xD7,0xAC,0xFD,0x5E,0x00
};
char b[]="Flag{This_a_Flag}";
int main ()
{
    char flag[256]="0";
    sub_8048E24(a,28,b,17);
    for(int i = 0 ; i<28; i ++ )
    {
        a[i]^=b[i%17];
        flag[i]=a[i];
    }
    char ans[256]={0};
    base64_decode(flag,ans,strlen(flag));
    cout<<ans<<endl;
}

动态调试获取rc4异或值

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<string>
#include<cstring>
#include<list>
#include<stdlib.h>
#include<windows.h>
#include<iostream>
#include<cstring>
#include<bitset>
#include<vector>
#include<stdlib.h>
#include<time.h>
#include<sstream>
#include<cstring>
/*base64.c*/  
#include "base64.h"  
using namespace std;
    //base64.c
#include"base64.h"
char base64char[] = "0123456789+/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
char c;
char* base64_encode(char* binData, char* base64, int binLength)
{
    int i = 0;
    int j = 0;
    int current = 0;
    for (i = 0; i < binLength; i += 3) {
        //获取第一个6位
        current = (*(binData + i) >> 2) & 0x3F;
        *(base64 + j++) = base64char[current];
        //获取第二个6位的前两位
        current = (*(binData + i) << 4) & 0x30;
        //如果只有一个字符,那么需要做特殊处理
        if (binLength <= (i + 1)) {
            *(base64 + j++) = base64char[current];
            *(base64 + j++) = '=';
            *(base64 + j++) = '=';
            break;
        }
        //获取第二个6位的后四位
        current |= (*(binData + i + 1) >> 4) & 0xf;
        *(base64 + j++) = base64char[current];
        //获取第三个6位的前四位
        current = (*(binData + i + 1) << 2) & 0x3c;
        if (binLength <= (i + 2)) {
            *(base64 + j++) = base64char[current];
            *(base64 + j++) = '=';
            break;
        }
        //获取第三个6位的后两位
        current |= (*(binData + i + 2) >> 6) & 0x03;
        *(base64 + j++) = base64char[current];
        //获取第四个6位
        current = *(binData + i + 2) & 0x3F;
        *(base64 + j++) = base64char[current];
    }
    *(base64 + j) = '\0';
    return base64;
}

char* base64_decode(char const* base64Str, char* debase64Str, int encodeStrLen)
{
    int i = 0;
    int j = 0;
    int k = 0;
    char temp[4] = "";

    for (i = 0; i < encodeStrLen; i += 4) {
        for (j = 0; j < 64; j++) {
            if (*(base64Str + i) == base64char[j]) {
                temp[0] = j;
            }
        }

        for (j = 0; j < 64; j++) {
            if (*(base64Str + i + 1) == base64char[j]) {
                temp[1] = j;
            }
        }

        for (j = 0; j < 64; j++) {
            if (*(base64Str + i + 2) == base64char[j]) {
                temp[2] = j;
            }
        }

        for (j = 0; j < 64; j++) {
            if (*(base64Str + i + 3) == base64char[j]) {
                temp[3] = j;
            }
        }

        *(debase64Str + k++) = ((temp[0] << 2) & 0xFC) | ((temp[1] >> 4) & 0x03);
        if (*(base64Str + i + 2) == '=')
            break;

        *(debase64Str + k++) = ((temp[1] << 4) & 0xF0) | ((temp[2] >> 2) & 0x0F);
        if (*(base64Str + i + 3) == '=')
            break;

        *(debase64Str + k++) = ((temp[2] << 6) & 0xF0) | (temp[3] & 0x3F);
    }
    return debase64Str;
}

int a[]={
    0xE8,0xD8,0xBD,0x91,0x87,0x1A,0x01,0x0E,0x56,0x0F
    ,0x53,0xF4,0x88,0x96,0x82,0xF9,0x61,0x42,0x0A,0xF2,0xAB
    ,0x08,0xFE,0xD7,0xAC,0xFD,0x5E,0x00
};
char b[]="Flag{This_a_Flag}";
int tmp[]={
    0xcb,0xcd,0x98,0xc2,0x8f,0x0,0x58,0x36,0x44,0x65,
    0x6a,0xc5,0xaf,0xcd,0x89,0xea,0x72,0x4a,0x56,0xc1,
    0xa0,0x3d,0x9f,0xd6,0xfd,0xe2,0x4e,0x5c,0x3f,0xd,
    0xe,0x47,0x8b,0x8a,0x45,0x39,0xcb,0xa4,0xbf,0xf2,
    0x79,0x7c,0x3a,0x6b,0xe8,0x2c,0x8b,0x1a,0x60,0x60,
    0x8e,0x7f,0x76,0x83,0x8e,0x1a
};
int main ()
{
    char flag[256]="0";
    for(int i= 0 ; i< 28; i ++ )
    {
        a[i]^=tmp[i];
    }
    for(int i = 0 ; i<28; i ++ )
    {
        a[i]^=b[i%17];
        flag[i]=a[i];
    }
    char ans[256]={0};
    base64_decode(flag,ans,strlen(flag));
    cout<<ans<<endl;
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇