终于体验到什么叫一杯茶,一包烟,一个bug改一天了
。
- 下面总结一下base64:
百度百科上面讲 “Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法
”。在ASCII码中规定,0126这95个字符属于可打印字符。base64索引表: 直接上两张图就能看懂base64的编码方式。
3个字符一组,高位补0,"="填充
。
下面直接上该两天bug的成果,应该还有其他没发现的bug。写的比较麻烦:
#include<stdio.h>
#include<string.h>
const char* base64_index = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
void encode(unsigned char* encodeStr){
unsigned char decode[1001] = {0}, exc;
int yu, len, i = 0, j = 0;
len = strlen(encodeStr);
yu = len % 3;
while(j < len - 3){
decode[0 + i] = encodeStr[0 + j] >> 2;
exc = (encodeStr[0 + j] << 4) & 0x30;
decode[1 + i] = (encodeStr[1 + j] >> 4) | exc;
exc = (encodeStr[1 + j] << 2) & 0x3c;
decode[2 + i] = encodeStr[2 + j] >> 6 | exc;
decode[3 + i] = encodeStr[2 + j] & 0x3f;
i += 4;
j = i - (i/4);
}
//最后三位单独处理
if(yu == 0){
decode[0 + i] = encodeStr[0 + j] >> 2;
exc = (encodeStr[0 + j] << 4) & 0x30;
decode[1 + i] = (encodeStr[1 + j] >> 4) | exc;
exc = (encodeStr[1 + j] << 2) & 0x3c;
decode[2 + i] = encodeStr[2 + j] >> 6 | exc;
decode[3 + i] = encodeStr[2 + j] & 0x3f;
}
else if(yu == 1){
decode[0 + i] = encodeStr[0 + j] >> 2;
exc = (encodeStr[0 + j] << 4) & 0x30;
decode[1 + i] = exc;
decode[2 + i] = 64;
decode[3 + i] = 64;
}
else if(yu == 2){
decode[0 + i] = encodeStr[0 + j] >> 2;
exc = (encodeStr[0 + j] << 4) & 0x30;
decode[1 + i] = (encodeStr[1 + j] >> 4) | exc;
exc = (encodeStr[1 + j] << 2) & 0x3c;
decode[2 + i] = exc;
decode[3 + i] = 64;
}
i = 0;
while(decode[i] || decode[i + 1]){ //这里针对形如0、4、8这种特殊字符
printf("%c", base64_index[decode[i]]);
i++;
}
puts("");
return ;
}
void decode(unsigned char* decodeStr){
unsigned char* decode[1001] = {0}, exc;
int len, i = 0, j;
len = strlen(decodeStr);
while(i < len){
for(j = 0; j < 65; j++)
if(decodeStr[i] == base64_index[j]){
decodeStr[i] = j;
break;
}
i++;
}
i = 0; j = 0;
while(i < len - 4){
decode[j + 0] = (decodeStr[i + 0] << 2) | ((decodeStr[i + 1] >> 4) & 0x3);
decode[j + 1] = (decodeStr[i + 1] << 4) | ((decodeStr[i + 2] >> 2) & 0xf);
decode[j + 2] = (decodeStr[i + 2] << 6) | (decodeStr[i + 3] & 0x3f);
i += 4;
j += 3;
}
decode[j + 0] = (decodeStr[i + 0] << 2) | ((decodeStr[i + 1] >> 4) & 0x3);
if(decodeStr[i + 2] != 64)
decode[j + 1] = (decodeStr[i + 1] << 4) | ((decodeStr[i + 2] >> 2) & 0xf);
if(decodeStr[i + 3] != 64)
decode[j + 2] = (decodeStr[i + 2] << 6) | (decodeStr[i + 3] & 0x3f);
i = 0;
while(decode[i]){
printf("%c", decode[i++]);
}
puts("");
return ;
}
int main()
{
int flag;
unsigned char encodeStr[1001] = {0};
unsigned char decodeStr[1001] = {0};
while(1){
printf("1.加密\n2.解密\n");
scanf("%d", &flag);
if(flag == 1){
printf("输入明文: ");
scanf("%s", decodeStr);
printf("密文: ");
encode(decodeStr);
}
if(flag == 2){
printf("输入密文: ");
scanf("%s", encodeStr);
printf("明文: ");
decode(encodeStr);
}
}
}
拖进ida中伪代码相差不大。锻炼一下自己的汇编功底。根据源代码再看汇编会容易很多,这里只挑了主要的加密算法分析,解密算法类似。
.text:004013C8 mov edx, [ebp+j]
.text:004013CB mov eax, [ebp+unk] ; 相当于encodeStr[0 + j]
.text:004013CE add eax, edx
.text:004013D0 movzx eax, byte ptr [eax] ; 将eax高位用0填充,后面同理
.text:004013D3 shr al, 2 ; 右移两位
.text:004013D6 mov edx, eax
.text:004013D8 lea ecx, [ebp+var_402] ; 取明文数组地址
.text:004013DE mov eax, [ebp+i]
.text:004013E1 add eax, ecx ; 这里eax存的是数组的地址
.text:004013E3 mov [eax], dl
.text:004013E5 mov edx, [ebp+j]
.text:004013E8 mov eax, [ebp+unk]
.text:004013EB add eax, edx
.text:004013ED movzx eax, byte ptr [eax]
.text:004013F0 movzx eax, al
.text:004013F3 shl eax, 4 ; 左移四位与0x30与运算
.text:004013F6 and eax, 30h
.text:004013F9 mov [ebp+exc], al
.text:004013FC mov eax, [ebp+i]
.text:004013FF lea edx, [eax+1]
.text:00401402 mov eax, [ebp+j]
.text:00401405 add eax, 1 ; encodeStr[1 + j]
.text:00401408 mov ecx, eax
.text:0040140A mov eax, [ebp+unk]
.text:0040140D add eax, ecx
.text:0040140F movzx eax, byte ptr [eax]
.text:00401412 shr al, 4 ; 右移4位,或运算
.text:00401415 or al, [ebp+exc]
.text:00401418 mov byte ptr [ebp+edx+var_402], al ; decode[1 + i]
.text:0040141F mov eax, [ebp+j]
.text:00401422 add eax, 1
.text:00401425 mov edx, eax
.text:00401427 mov eax, [ebp+unk] ; encodeStr[1 + j]
.text:0040142A add eax, edx
.text:0040142C movzx eax, byte ptr [eax]
.text:0040142F movzx eax, al
.text:00401432 shl eax, 2
.text:00401435 and eax, 3Ch ; 左移2位,与运算,保存到exc中
.text:00401438 mov [ebp+exc], al
.text:0040143B mov eax, [ebp+i]
.text:0040143E lea edx, [eax+2]
.text:00401441 mov eax, [ebp+j]
.text:00401444 add eax, 2 ; encodeStr[2 + j]
.text:00401447 mov ecx, eax
.text:00401449 mov eax, [ebp+unk]
.text:0040144C add eax, ecx
.text:0040144E movzx eax, byte ptr [eax]
.text:00401451 shr al, 6 ; 右移6位,或运算
.text:00401454 or al, [ebp+exc]
.text:00401457 mov byte ptr [ebp+edx+var_402], al ; decode[2 + i]
.text:0040145E mov eax, [ebp+i]
.text:00401461 add eax, 3 ; decode[3 + i]
.text:00401464 mov edx, [ebp+j]
.text:00401467 add edx, 2 ; encodeStr[2 + j]
.text:0040146A mov ecx, edx
.text:0040146C mov edx, [ebp+unk]
.text:0040146F add edx, ecx
.text:00401471 movzx edx, byte ptr [edx]
.text:00401474 and edx, 3Fh ; &0x3f
.text:00401477 mov byte ptr [ebp+eax+var_402], dl
.text:0040147E add [ebp+i], 4 ; i + 4
.text:00401482 mov eax, [ebp+i]
.text:00401485 lea edx, [eax+3]
.text:00401488 test eax, eax
.text:0040148A cmovs eax, edx
.text:0040148D sar eax, 2
.text:00401490 mov edx, eax ; i / 4
.text:00401492 mov eax, [ebp+i]
.text:00401495 sub eax, edx
.text:00401497 mov [ebp+j], eax
.text:0040149A
.text:0040149A loc_40149A: ; CODE XREF: _encode+73↑j
.text:0040149A mov eax, [ebp+var_14]
.text:0040149D sub eax, 3
.text:004014A0 cmp eax, [ebp+j] ; while(j < len - 3)
.text:004014A3 jg loc_4013C8