0%

re-base64编码及其变种

base64编码及其变种

最近空闲下来了,还是花点时间找点题目练练,base64在逆向中也很常见,不过都不是常规base64,今天花些时间来学习下base64以及其变种

编码原理:将3个字节转换成4个字节((3 X 8)=24=(4X6)),先读入3个字节,每读一个字节,左移8位,再右移四次,每次6位,这样就有4个字节了。
解码原理:将4个字节转换成3个字节,先读入4个6位(用或运算),每次左移6位,再右移3次,每次8位,这样就还原了

原文来自皮皮猪

普通的base64

变种base64–带偏移加自定义表的

这里以i春秋 9月赛一道题目进行分析,re_normal_confused

这里base64前面还是常规的,他将表自定义了,然后同时,将表偏移了24位,这里表本来是65位长度,不过没啥用,取还是取64位,因为有&0x3f

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
_BYTE *__fastcall base64encode(size_t a1, __int64 a2, int length, __int64 data)
{
__int64 v4; // rdx
char v6[8]; // [rsp+20h] [rbp-30h]
_BYTE *v7; // [rsp+28h] [rbp-28h]
int i; // [rsp+30h] [rbp-20h]
int v9; // [rsp+34h] [rbp-1Ch]
_BYTE *v10; // [rsp+38h] [rbp-18h]
int v11; // [rsp+44h] [rbp-Ch]
int v12; // [rsp+48h] [rbp-8h]
int v13; // [rsp+4Ch] [rbp-4h]
__int64 v14; // [rsp+60h] [rbp+10h]
int v15; // [rsp+68h] [rbp+18h]

v14 = data;
v15 = length;
v13 = 0;
v7 = 0LL;
v10 = 0LL;
v9 = 0;
i = 0;
v12 = length / 3;
v11 = length % 3;
if ( length % 3 > 0 )
++v12;
v12 = 4 * v12 + 1;
v7 = malloc(a1);
if ( !v7 )
exit(a1);
v10 = v7;
while ( v9 < v15 )
{
v11 = 0;
v13 = 0;
while ( v11 <= 2 && v9 < v15 ) // 这里是获取三个字节,因为base64以3个字节为一个单位
{
v4 = v9;
v13 = (v13 << 8) | *(v9++ + v14);
++v11;
}
v13 <<= 8 * (3 - v11); // 这里是处理未满三个字节的
// 若满三个字节,则不左移
for ( i = 0; i <= 3; ++i )
{
if ( v11 >= i )
{
v4 = (v13 >> 6 * (3 - i)) & 0x3F;
v6[i] = (v13 >> 6 * (3 - i)) & 0x3F; // 0x3f 00111111 其实就是取后6位,每次取6位
}
else
{
v6[i] = 64;
}
v4 = aYrAoywcfben5lb[sub_401711(a1, a2, v4, v6[i])];// 这个函数将表偏移了24个字节
*v10++ = v4;
}
}
*v10 = 0;
return v7;
}
/* Orphan comments:
这里用寄存器ecx传参,ida无法识别,其实就是a1 = v4
*/

这里编码过后数据为:

1
B4QrGVzkpZVeHssap5HEgWfSQQ0zmMAA

表为:

1
yr+aOYWCfBeN5lb8v7QdxZuAMq/J0tTI1RkSimKFwnczo2VXpPshL4_UgjH6DEG39

我们需要对齐解码,也就是将表偏移后在进行自定义表解码

利用python转换

1
2
3
4
5
>>> string = "yr+aOYWCfBeN5lb8v7QdxZuAMq/J0tTI1RkSimKFwnczo2VXpPshL4_UgjH6DEG39"
>>> string[24:] + string[0:24]
'Mq/J0tTI1RkSimKFwnczo2VXpPshL4_UgjH6DEG39yr+aOYWCfBeN5lb8v7QdxZuA'
>>> string[24:] + string[0:23]
'Mq/J0tTI1RkSimKFwnczo2VXpPshL4_UgjH6DEG39yr+aOYWCfBeN5lb8v7QdxZu'

这里只需要取64位就行,去掉一位,方便解码

python2

1
2
3
4
5
6
7
8
9
10
11
12
import string
import base64
STANDARD_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
CUSTOM_ALPHABET = 'Mq/J0tTI1RkSimKFwnczo2VXpPshL4_UgjH6DEG39yr+aOYWCfBeN5lb8v7QdxZu'
ENCODE_TRANS = string.maketrans(STANDARD_ALPHABET, CUSTOM_ALPHABET)
DECODE_TRANS = string.maketrans(CUSTOM_ALPHABET, STANDARD_ALPHABET)
def encode(input):
return base64.b64encode(input).translate(ENCODE_TRANS)
def decode(input):
return base64.b64decode(input.translate(DECODE_TRANS))

print(decode("B4QrGVzkpZVeHssap5HEgWfSQQ0zmMAA").encode("hex"))

python3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import base64
import binascii
STANDARD_ALPHABET = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
CUSTOM_ALPHABET = b'Mq/J0tTI1RkSimKFwnczo2VXpPshL4_UgjH6DEG39yr+aOYWCfBeN5lb8v7QdxZu'
ENCODE_TRANS = bytes.maketrans(STANDARD_ALPHABET, CUSTOM_ALPHABET)
DECODE_TRANS = bytes.maketrans(CUSTOM_ALPHABET, STANDARD_ALPHABET)
def encode(input):
return bytes.decode(base64.b64encode(input)).translate(ENCODE_TRANS)
def decode(input):
return base64.b64decode(input.translate(DECODE_TRANS))


result = decode("B4QrGVzkpZVeHssap5HEgWfSQQ0zmMAA")
print(binascii.hexlify(result))

解码过后会多出几个00

1
c9deea9964ca63e5b389a6ac6358a582fc4befb113340000

去掉即可

本文作者:NoOne
本文地址https://noonegroup.xyz/posts/d495385/
版权声明:转载请注明出处!