内容简介:记录DDCTF中一道非常需要耐心的逆向题
这题出现在DDCTF的level8,题目给了两张图片和一段文字,稍后我会提供附件。
挑战:《Crack me if you can》
赛题背景:图片信息隐藏与数字水印技术一直是安全研究领域的热门话题之一,本挑战结合了图片内嵌、算法逆向等知识点,考察了挑战者的综合技术素养。
赛题描述:本题是一张图片,请试分析图片中隐藏的内嵌文件,逆向 Crack me 算法并得到 DDCTF-65f9 输入所对应的密钥。
评分标准:密钥正确则可进入下一题。
图片1:
图片2(名字crackme.png,关键附件,请从下文中下载原图):
附件下载: http://pan.baidu.com/s/1jIMaBum 密码:5cah
从图片到程序
首先由名字crackme,我们知道了这是一道re题,但他给了一张图片。
我们用010editor打开他。
emmm,标准的jpg文件头,果然png的后缀名是假的,jpg的文件结尾标志是FFD9,ctrl+F查找
发现后面附加了一段数据,把这段数据先单独存下来。
不知是不是直觉,我猜这段数据是zlib的压缩数据,用 python 写脚本解压一下。
import zlib
enc = open('dump','rb').read()
dec = zlib.decompress(enc)
print dec
输出了一段base64,由于数据过长,就不贴了。我把他base64解码后写到文件。
import zlib
enc = open('dump','rb').read()
dec = zlib.decompress(enc).decode('base64')
open('dump_base64','wb').write(dec)
再用010editor打开,发现我们熟悉的zip文件头PK被改成了KP(滑稽)
改过来以后得到压缩包 dump.zip 。
然而解压需要密码。
结合题目提供的第一张图,这是一个除零错误。
试一试就知道了。
2 / 0
Traceback (most recent call last):
File "C:\Users\veritas501\Desktop\study\test.py", line 1, in <module>
2/0
ZeroDivisionError: integer division or modulo by zero
[Finished in 0.1s]
所以压缩密码是 integer division or modulo by zero 。
成功得到 crackme.exe !!
IDA加OD动静态分析
OD里下 GetDlgItemTextA 断点,来到获取输入的地址 0x00**1EE4 ,IDA也相应的来到 0x00**1EE4 。
接下来在IDA中疯狂整理代码逻辑和变量名。这段辛酸过程省略,不想整理的话我上面的附件里也提供了我当时做题时整理好的idb文件,直接载入也行。
首先程序里有一段240bytes长的char * head,作为常量,结合输入的password(即mail)进行大量的运算,所得的值1和输入的uasename通过某种运算的到的值2相等。
整理一下逻辑。
username题目告诉我们了,因为用了strcat,所以key可以推出,key到IV3由于是正向计算,直接在OD中动态跟一下结果IV3也就出来了。又因为IV2和IV3是相等的关系,所以IV2也可以直接得到。head到hash是正向算法,hash也可以直接动态跟出来。
head->hash\
IV1\
mail_mid->pwd/ IV2\
head/ equal!!
username->key->IV3/
username:DDCTF-65f9
IV3:IV2:'e8d8e2ceaf9de076a0f211f5a1895352'.encode('hex')
len IV2,IV3 = 16
hash:
7DEC14283116611B3CBD497513843B3B304D171BF021FF0C9E8D4692307EBC7AE8223FB03CE6FE1C6EC09B6C957C40A49D8D2CC63F13953F8973EDF80CD3B7775C5DE5D0BE87E7B62AD148729F60649E3D059704628685678A0AEC8BC80ED5F70AB1B095042BFD3FCDA94906961437F5A8009DBC70D01C4591D583A6FE967A9992CF10E197BDBAAD3BE159E448393F08DAC047366783936D408B2DA876AFB530CAA6F54FAD0AF83A6F860B9E8B40EC1D
len hash :0xB0
所以现在的关键是需要对IV12IV3这个算法求逆,由IV2和head推出IV1。然后再对hash2IV1这个函数求逆,由IV1和hash推出pwd。然后pwd直接encode_hex就能得到mail_mid。
分析IV12IV2
又是一段艰苦的逆向,最后发现就是一个稍微变化过的aes解码函数。。。
当然逆向这东西,事后看看都觉得简单,只有自己逆过才懂得艰辛。
用python写出加密和解密函数:
head = '4E5332303137434D2D44444354462D006469646963687578696E672E636F6D00E3E22A86D2D569CBFF912D88ABD70088795A7C0A1A320972735C6E5C1033035C7E73C8AAACA6A16153378CE9F8E08C61B0FD53F4AACF5A86D99334DAC9A037861090A478BC360519EF0189F017E105912C5455E7869B0F615F083BBB96A80C3DDD94FDCB61A2F8D28EA37122994274B3434E26BBC5D529DA9ADD12610C751E5C0DB91FCF6C1BE71DE2B8963F7BFAE28CAF1526946AC00F4EF01D1D2FFC680373A928A37DC5334460278BD25F5C7130D34D8C69C6274C6688D7517BA72B3978D4CBAF95E70E9CD187291703D87566330B'.decode('hex')
box = 'E2D681A62AFEC53CBDAF540A75D85120E9BBED7A92EE48A46E03B56DB8A5597DDF4A391A4DD3C722EC50DEFCF3C95CC8899183D7F4438874C06A5896020837720C7C0DA92F7E6980684C352D40BE9A36F72C8FC6B6DBCE09BCEB04D0A8C411B20552B1D415A2972E90642963318AE8CA873E762321D20B257824E034A1D90EAC8D0060E4AA5D0FEA3827BA7FA3703216FB66DA06653DBF3B2871E162F8AD9F4E9D42F2CF1285A04F672B93F0824B01561C9CE513C2FAFFDC9B9498E3F684EF77E76B10465EB386B0F9176F73D1AE7B446CAB1ED55B9E265FC33A14181B3F79F1FD8EB7C1CC55F5455357A747958BCD6149198C1F305A99411D33B4E6CB07DDB9'.decode('hex')
inv_box = [0]*256
inv_a = [3,1,1,2]
a = [9,0xe,0xb,0xd]
int_1 = 14
def AddRoundKey(tmp,head,k):
for j in range(4):
tmp[j] ^= ord(head[16*k+4*j])
tmp[j+4] ^= ord(head[16*k+4*j+1])
tmp[j+8] ^= ord(head[16*k+4*j+2])
tmp[j+12] ^= ord(head[16*k+4*j+3])
return tmp
def ShiftRows(tmp):
for i in range(1,4):
for j in range(i):
v3 = tmp[4*i+3]
for k in range(3,0,-1):
tmp[4*i+k] = tmp[4*i+k-1]
tmp[4*i] = v3
return tmp
def inv_ShiftRows(tmp):
for i in range(1,4):
for j in range(i):
v3 = tmp[4*i]
for k in range(0,3):
tmp[4*i+k] = tmp[4*i+k+1]
tmp[4*i+3] = v3
return tmp
def SubBytes(tmp):
for i in range(4):
for j in range(4):
tmp[4*i+j] = ord(box[16 * (tmp[4*i+j] & 0xF) + (( tmp[4*i+j] & 0xF0) >> 4)])
return tmp
def inv_SubBytes(tmp):
for i in range(256):
inv_box[ord(box[i])] = i
for i in range(4):
for j in range(4):
tmp[4*i+j] = inv_box[tmp[4*i+j]]
tmp[4*i+j] = 16 * (tmp[4*i+j] & 0xF) + (( tmp[4*i+j] & 0xF0) >> 4)
return tmp
def mix_single_column(v6):
d = [0]*4
d[0] = gmult(a[0],v6[0])^gmult(a[3],v6[1])^gmult(a[2],v6[2])^gmult(a[1],v6[3]);
d[1] = gmult(a[1],v6[0])^gmult(a[0],v6[1])^gmult(a[3],v6[2])^gmult(a[2],v6[3]);
d[2] = gmult(a[2],v6[0])^gmult(a[1],v6[1])^gmult(a[0],v6[2])^gmult(a[3],v6[3]);
d[3] = gmult(a[3],v6[0])^gmult(a[2],v6[1])^gmult(a[1],v6[2])^gmult(a[0],v6[3]);
return d
def gmult(aa,bb):
p=0
hbs=0
for i in range(8):
if (bb&1):
p ^= aa
hbs=aa&0x80
aa<<=1
aa = aa&0xff
if hbs:
aa ^= 0x1b
bb>>=1
return p
def mix_columns(tmp):
v6 = [0]*4
for i in range(4):
for j in range(4):
v6[j] = tmp[4*j+i]
v6 = mix_single_column(v6)
for j in range(4):
tmp[4*j+i] = v6[j]
return tmp
def inv_mix_columns(tmp):
v6 = [0]*4
for i in range(4):
for j in range(4):
v6[j] = tmp[4*j+i]
v6 = inv_mix_single_column(v6)
for j in range(4):
tmp[4*j+i] = v6[j]
return tmp
def inv_mix_single_column(v6):
d = [0]*4
d[0] = gmult(inv_a[0],v6[0])^gmult(inv_a[3],v6[1])^gmult(inv_a[2],v6[2])^gmult(inv_a[1],v6[3]);
d[1] = gmult(inv_a[1],v6[0])^gmult(inv_a[0],v6[1])^gmult(inv_a[3],v6[2])^gmult(inv_a[2],v6[3]);
d[2] = gmult(inv_a[2],v6[0])^gmult(inv_a[1],v6[1])^gmult(inv_a[0],v6[2])^gmult(inv_a[3],v6[3]);
d[3] = gmult(inv_a[3],v6[0])^gmult(inv_a[2],v6[1])^gmult(inv_a[1],v6[2])^gmult(inv_a[0],v6[3]);
return d
def print_iv(iv):
out=''
for i in range(len(iv)):
out += chr(iv[i])
print out.encode('hex')
def enc(iv1):
print iv1
iv1 = list(iv1.decode('hex'))
for i in range(len(iv1)):
iv1[i] = ord(iv1[i])
tmp=[0]*16
iv2=[0]*16
for i in range(4):
for j in range(4):
tmp[4*i+j] = iv1[4*j+i]
tmp = AddRoundKey(tmp,head,int_1)
for k in range(int_1-1,0,-1):
tmp = ShiftRows(tmp)
tmp = SubBytes(tmp)
tmp = AddRoundKey(tmp,head,k)
tmp = mix_columns(tmp)
tmp = ShiftRows(tmp)
tmp = SubBytes(tmp)
tmp = AddRoundKey(tmp,head,0)
for i in range(4):
for j in range(4):
iv2[4*j+i] = tmp[4*i+j]
for i in range(len(iv2)):
iv2[i] = chr(iv2[i])
iv2 = ''.join(iv2)
iv2 = iv2.encode('hex')
return iv2
def dec(iv1):
print iv1
iv1 = list(iv1.decode('hex'))
for i in range(len(iv1)):
iv1[i] = ord(iv1[i])
tmp=[0]*16
iv2=[0]*16
for i in range(4):
for j in range(4):
tmp[4*i+j] = iv1[4*j+i]
tmp = AddRoundKey(tmp,head,0)
tmp = inv_SubBytes(tmp)
tmp = inv_ShiftRows(tmp)
for k in range(1,int_1):
tmp = inv_mix_columns(tmp)
tmp = AddRoundKey(tmp,head,k)
tmp = inv_SubBytes(tmp)
tmp = inv_ShiftRows(tmp)
tmp = AddRoundKey(tmp,head,int_1)
for i in range(4):
for j in range(4):
iv2[4*j+i] = tmp[4*i+j]
for i in range(len(iv2)):
iv2[i] = chr(iv2[i])
iv2 = ''.join(iv2)
iv2 = iv2.encode('hex')
return iv2
iv2 = 'e8d8e2ceaf9de076a0f211f5a1895352'
iv1 = dec(iv2)
print iv1
得到 iv1:e3c8f0eb7ad23ff182c8d87383f44918
分析hash2IV1函数
又是一阵疯狂的逆向加整理。
如果你直接在ida里按f5的话,你会得到这样的代码:
int __cdecl hash2IV1(char *hash, char *pwd, char *IV1)
{
unsigned int v3; // ST14_4@3
unsigned int v4; // ST24_4@3
char *v5; // ST18_4@3
unsigned int v6; // ST0C_4@3
int v7; // ST14_4@3
int v8; // ST0C_4@4
int v9; // ST24_4@4
int result; // eax@4
int xxx4; // [sp+Ch] [bp-20h]@1
int xxx1; // [sp+10h] [bp-1Ch]@1
char *v13; // [sp+18h] [bp-14h]@1
int xxx3; // [sp+1Ch] [bp-10h]@1
int xxx2; // [sp+24h] [bp-8h]@1
unsigned int i; // [sp+28h] [bp-4h]@1
xxx2 = *((_DWORD *)pwd + 1);
xxx4 = *((_DWORD *)pwd + 3);
xxx3 = *((_DWORD *)pwd + 2) - *((_DWORD *)hash + 0x2B);
xxx1 = *(_DWORD *)pwd - *((_DWORD *)hash + 0x2A);
v13 = hash + 0xA4;
for ( i = 0; i < 0x14; ++i )
{
v3 = ((unsigned int)(xxx1 * (2 * xxx3 + 1)) >> 25) | (xxx1 * (2 * xxx3 + 1) << 7);
v4 = v3 ^ (((unsigned int)(xxx2 - *(_DWORD *)v13) >> (32 - ((unsigned int)(xxx3 * (2 * xxx1 + 1)) >> 23))) | ((xxx2 - *(_DWORD *)v13) << ((unsigned int)(xxx3 * (2 * xxx1 + 1)) >> 23)));
v5 = v13 - 4;
v6 = (((unsigned int)(xxx3 * (2 * xxx1 + 1)) >> 23) | (xxx3 * (2 * xxx1 + 1) << 9)) ^ (((unsigned int)(xxx4 - *(_DWORD *)v5) >> (32 - (32 - v3))) | ((xxx4 - *(_DWORD *)v5) << (32 - v3)));
v13 = v5 - 4;
v7 = v6;
xxx4 = xxx3;
xxx3 = v4;
xxx2 = xxx1;
xxx1 = v7;
}
v8 = xxx4 - *(_DWORD *)v13;
v9 = xxx2 - *((_DWORD *)v13 - 1);
*((_DWORD *)IV1 + 3) = xxx1;
*(_DWORD *)IV1 = v9;
*((_DWORD *)IV1 + 1) = xxx3;
result = v8;
*((_DWORD *)IV1 + 2) = v8;
return result;
}
这种代码你想写逆算法根本是不可能的,我们要先对这段代码进行整理和改编。
由于用了一些不同数据长度的类型的转换,所以这里我用 c语言 来写。
include <stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
typedef unsigned char byte;
typedef unsigned int uint;
byte pwd[] = { 0x59 ,0x43 ,0x29 ,0x31 ,0x19 ,0xA8 ,0x45 ,0xE9 ,0xBB ,0xDB ,0xDE ,0x5A ,0x36 ,0x9C ,0x1F ,0x50 };
byte iv1[] = { 0xe3 ,0xc8 ,0xf0 ,0xeb ,0x7a ,0xd2 ,0x3f ,0xf1 ,0x82 ,0xc8 ,0xd8 ,0x73 ,0x83 ,0xf4 ,0x49 ,0x18 };
byte out[] = { 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 };
byte hashcode[] = { 0x7D,0xEC,0x14,0x28,0x31,0x16,0x61,0x1B,0x3C,0xBD,0x49,0x75,0x13,0x84,0x3B,0x3B,0x30,0x4D,0x17,0x1B,0xF0,0x21,0xFF,0x0C,0x9E,0x8D,0x46,0x92,0x30,0x7E,0xBC,0x7A,0xE8,0x22,0x3F,0xB0,0x3C,0xE6,0xFE,0x1C,0x6E,0xC0,0x9B,0x6C,0x95,0x7C,0x40,0xA4,0x9D,0x8D,0x2C,0xC6,0x3F,0x13,0x95,0x3F,0x89,0x73,0xED,0xF8,0x0C,0xD3,0xB7,0x77,0x5C,0x5D,0xE5,0xD0,0xBE,0x87,0xE7,0xB6,0x2A,0xD1,0x48,0x72,0x9F,0x60,0x64,0x9E,0x3D,0x05,0x97,0x04,0x62,0x86,0x85,0x67,0x8A,0x0A,0xEC,0x8B,0xC8,0x0E,0xD5,0xF7,0x0A,0xB1,0xB0,0x95,0x04,0x2B,0xFD,0x3F,0xCD,0xA9,0x49,0x06,0x96,0x14,0x37,0xF5,0xA8,0x00,0x9D,0xBC,0x70,0xD0,0x1C,0x45,0x91,0xD5,0x83,0xA6,0xFE,0x96,0x7A,0x99,0x92,0xCF,0x10,0xE1,0x97,0xBD,0xBA,0xAD,0x3B,0xE1,0x59,0xE4,0x48,0x39,0x3F,0x08,0xDA,0xC0,0x47,0x36,0x67,0x83,0x93,0x6D,0x40,0x8B,0x2D,0xA8,0x76,0xAF,0xB5,0x30,0xCA,0xA6,0xF5,0x4F,0xAD,0x0A,0xF8,0x3A,0x6F,0x86,0x0B,0x9E,0x8B,0x40,0xEC,0x1D };
void printout(byte* pout){
int unequal = 0;
for (int i = 0; i < 16; i++) {
unequal |= (pwd[i] ^ pout[i]);
printf("%x,", pout[i]);
}
printf("\n\n");
if (!unequal) {
printf("true!!!\n");
}
else {
printf("FALSE\n");
}
}
inlineuintrol(uint a, uint off){
return (a << off) | (a >> (32 - off));
}
inlineuintror(uint a, uint off){
return (a << (32 - off)) | (a >> off);
}
void enc(byte* in_pwd){
uint xxx1, xxx2, xxx3, xxx4;
byte * v13;
uint a, b, c, d;
xxx1 = *((uint*)in_pwd) - *((uint*)hashcode + 0x2a);
xxx2 = *((uint*)in_pwd + 1);
xxx3 = *((uint*)in_pwd + 2) - *((uint*)hashcode + 0x2b);
xxx4 = *((uint*)in_pwd + 3);
for (int i = 0; i < 0x14; ++i) {
v13 = hashcode + 0xa4 - i * 8;
a = rol(xxx1 * (2 * xxx3 + 1), 7);
b = rol(xxx2 - *(uint *)v13, ((xxx3 * (2 * xxx1 + 1)) >> 23));
c = rol(xxx3 * (2 * xxx1 + 1), 9);
d = ror(xxx4 - *(uint *)(v13 - 4), a);
xxx4 = xxx3;
xxx3 = a^b;
xxx2 = xxx1;
xxx1 = c^d;
}
*(uint *)out = xxx2 - *((uint *)hashcode);
*((uint *)out + 1) = xxx3;
*((uint *)out + 2) = xxx4 - *(uint *)(hashcode + 4);
*((uint *)out + 3) = xxx1;
}
从这改编过的代码中,我们可以明显看出轮加密的痕迹,也就是Feistel网络结构。
那逆算法就好写了。
include <stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
typedef unsigned char byte;
typedef unsigned int uint;
byte pwd[] = { 0x59 ,0x43 ,0x29 ,0x31 ,0x19 ,0xA8 ,0x45 ,0xE9 ,0xBB ,0xDB ,0xDE ,0x5A ,0x36 ,0x9C ,0x1F ,0x50 };
byte iv1[] = { 0xe3 ,0xc8 ,0xf0 ,0xeb ,0x7a ,0xd2 ,0x3f ,0xf1 ,0x82 ,0xc8 ,0xd8 ,0x73 ,0x83 ,0xf4 ,0x49 ,0x18 };
byte out[] = { 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 };
byte hashcode[] = { 0x7D,0xEC,0x14,0x28,0x31,0x16,0x61,0x1B,0x3C,0xBD,0x49,0x75,0x13,0x84,0x3B,0x3B,0x30,0x4D,0x17,0x1B,0xF0,0x21,0xFF,0x0C,0x9E,0x8D,0x46,0x92,0x30,0x7E,0xBC,0x7A,0xE8,0x22,0x3F,0xB0,0x3C,0xE6,0xFE,0x1C,0x6E,0xC0,0x9B,0x6C,0x95,0x7C,0x40,0xA4,0x9D,0x8D,0x2C,0xC6,0x3F,0x13,0x95,0x3F,0x89,0x73,0xED,0xF8,0x0C,0xD3,0xB7,0x77,0x5C,0x5D,0xE5,0xD0,0xBE,0x87,0xE7,0xB6,0x2A,0xD1,0x48,0x72,0x9F,0x60,0x64,0x9E,0x3D,0x05,0x97,0x04,0x62,0x86,0x85,0x67,0x8A,0x0A,0xEC,0x8B,0xC8,0x0E,0xD5,0xF7,0x0A,0xB1,0xB0,0x95,0x04,0x2B,0xFD,0x3F,0xCD,0xA9,0x49,0x06,0x96,0x14,0x37,0xF5,0xA8,0x00,0x9D,0xBC,0x70,0xD0,0x1C,0x45,0x91,0xD5,0x83,0xA6,0xFE,0x96,0x7A,0x99,0x92,0xCF,0x10,0xE1,0x97,0xBD,0xBA,0xAD,0x3B,0xE1,0x59,0xE4,0x48,0x39,0x3F,0x08,0xDA,0xC0,0x47,0x36,0x67,0x83,0x93,0x6D,0x40,0x8B,0x2D,0xA8,0x76,0xAF,0xB5,0x30,0xCA,0xA6,0xF5,0x4F,0xAD,0x0A,0xF8,0x3A,0x6F,0x86,0x0B,0x9E,0x8B,0x40,0xEC,0x1D };
void printout(byte* pout){
int unequal = 0;
for (int i = 0; i < 16; i++) {
unequal |= (pwd[i] ^ pout[i]);
printf("%x,", pout[i]);
}
printf("\n\n");
if (!unequal) {
printf("true!!!\n");
}
else {
printf("FALSE\n");
}
}
inlineuintrol(uint a, uint off){
return (a << off) | (a >> (32 - off));
}
inlineuintror(uint a, uint off){
return (a << (32 - off)) | (a >> off);
}
void enc(byte* in_pwd){
uint xxx1, xxx2, xxx3, xxx4;
byte * v13;
uint a, b, c, d;
xxx1 = *((uint*)in_pwd) - *((uint*)hashcode + 0x2a);
xxx2 = *((uint*)in_pwd + 1);
xxx3 = *((uint*)in_pwd + 2) - *((uint*)hashcode + 0x2b);
xxx4 = *((uint*)in_pwd + 3);
for (int i = 0; i < 0x14; ++i) {
v13 = hashcode + 0xa4 - i * 8;
a = rol(xxx1 * (2 * xxx3 + 1), 7);
b = rol(xxx2 - *(uint *)v13, ((xxx3 * (2 * xxx1 + 1)) >> 23));
c = rol(xxx3 * (2 * xxx1 + 1), 9);
d = ror(xxx4 - *(uint *)(v13 - 4), a);
xxx4 = xxx3;
xxx3 = a^b;
xxx2 = xxx1;
xxx1 = c^d;
}
*(uint *)out = xxx2 - *((uint *)hashcode);
*((uint *)out + 1) = xxx3;
*((uint *)out + 2) = xxx4 - *(uint *)(hashcode + 4);
*((uint *)out + 3) = xxx1;
}
void dec(byte* in_iv){
uint xxx1, xxx1_up, xxx2, xxx2_up, xxx3, xxx3_up, xxx4, xxx4_up;
byte * v13;
uint a, b, c, d;
xxx2 = *(uint *)in_iv + *((uint *)hashcode);
xxx3 = *((uint *)in_iv + 1);
xxx4 = *((uint *)in_iv + 2) + *(uint *)(hashcode + 4);;
xxx1 = *((uint *)in_iv + 3);
for (int i = 0x13; i >= 0; --i) {
v13 = hashcode + 0xa4 - i * 8;
xxx1_up = xxx2;
xxx3_up = xxx4;
a = rol(xxx1_up * (2 * xxx3_up + 1), 7);
c = rol(xxx3_up * (2 * xxx1_up + 1), 9);
b = xxx3^a;
d = xxx1^c;
xxx2_up = ror(b, ((xxx3_up * (2 * xxx1_up + 1)) >> 23)) + *(uint *)v13;
xxx4_up = rol(d, a) + *(uint *)(v13 - 4);
xxx4 = xxx4_up;
xxx3 = xxx3_up;
xxx2 = xxx2_up;
xxx1 = xxx1_up;
}
*((uint*)out) = xxx1 + *((uint*)hashcode + 0x2a);
*((uint*)out + 1) = xxx2;
*((uint*)out + 2) = xxx3 + *((uint*)hashcode + 0x2b);
*((uint*)out + 3) = xxx4;
}
int main(void){
dec(iv1);
printout(out);
system("pause");
return 0;
}
从而得到 pwd:93c65c807c3800b15f3600d449c64692
收尾
由格式知,我们的password(也就是mail)为 DDCTF-93c65c807c3800b15f3600d449c64692@didichuxing.com
总结这道题,不说前面的非re部分,难点主要在于求这两个的逆函数上。对此应当对常见的加密算法模式有比较透彻的理解。
而且从头到尾彻彻底底的写了一遍AES加密算法和AES的解密算法还真TM赤鸡呢!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
React Native开发指南
[美]艾森曼 / 黄为伟 / 人民邮电出版社 / 2016-6-1 / CNY 59.00
本书通过丰富的示例和详细的讲解,介绍了React Native这款JavaScript框架。在React Native中利用现有的JavaScript和React知识,就可以开发和部署功能完备的、真正原生的移动应用,并同时支持iOS与Android平台。除了框架本身的概念讲解之外,本书还讨论了如何使用第三方库,以及如何编写自己的Java或Objective-C的React Native扩展。一起来看看 《React Native开发指南》 这本书的介绍吧!