记录DDCTF中一道非常需要耐心的逆向题

栏目: Ruby · 发布时间: 6年前

内容简介:记录DDCTF中一道非常需要耐心的逆向题

这题出现在DDCTF的level8,题目给了两张图片和一段文字,稍后我会提供附件。

挑战:《Crack me if you can》

赛题背景:图片信息隐藏与数字水印技术一直是安全研究领域的热门话题之一,本挑战结合了图片内嵌、算法逆向等知识点,考察了挑战者的综合技术素养。

赛题描述:本题是一张图片,请试分析图片中隐藏的内嵌文件,逆向 Crack me 算法并得到 DDCTF-65f9 输入所对应的密钥。

评分标准:密钥正确则可进入下一题。

图片1:

记录DDCTF中一道非常需要耐心的逆向题

图片2(名字crackme.png,关键附件,请从下文中下载原图):

记录DDCTF中一道非常需要耐心的逆向题

附件下载: http://pan.baidu.com/s/1jIMaBum 密码:5cah

从图片到程序

首先由名字crackme,我们知道了这是一道re题,但他给了一张图片。

我们用010editor打开他。

记录DDCTF中一道非常需要耐心的逆向题

emmm,标准的jpg文件头,果然png的后缀名是假的,jpg的文件结尾标志是FFD9,ctrl+F查找

记录DDCTF中一道非常需要耐心的逆向题

发现后面附加了一段数据,把这段数据先单独存下来。

不知是不是直觉,我猜这段数据是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(滑稽)

记录DDCTF中一道非常需要耐心的逆向题

改过来以后得到压缩包 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 !!

记录DDCTF中一道非常需要耐心的逆向题

IDA加OD动静态分析

OD里下 GetDlgItemTextA 断点,来到获取输入的地址 0x00**1EE4 ,IDA也相应的来到 0x00**1EE4

接下来在IDA中疯狂整理代码逻辑和变量名。这段辛酸过程省略,不想整理的话我上面的附件里也提供了我当时做题时整理好的idb文件,直接载入也行。

首先程序里有一段240bytes长的char * head,作为常量,结合输入的password(即mail)进行大量的运算,所得的值1和输入的uasename通过某种运算的到的值2相等。

记录DDCTF中一道非常需要耐心的逆向题

整理一下逻辑。

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解码函数。。。

记录DDCTF中一道非常需要耐心的逆向题

当然逆向这东西,事后看看都觉得简单,只有自己逆过才懂得艰辛。

用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

记录DDCTF中一道非常需要耐心的逆向题

总结这道题,不说前面的非re部分,难点主要在于求这两个的逆函数上。对此应当对常见的加密算法模式有比较透彻的理解。

而且从头到尾彻彻底底的写了一遍AES加密算法和AES的解密算法还真TM赤鸡呢!


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

大话数据结构

大话数据结构

程杰 / 清华大学出版社 / 2011-6 / 59.00元

本书为超级畅销书《大话设计模式》作者程杰潜心三年推出的扛鼎之作!以一个计算机教师教学为场景,讲解数据结构和相关算法的知识。通篇以一种趣味方式来叙述,大量引用了各种各样的生活知识来类比,并充分运用图形语言来体现抽象内容,对数据结构所涉及到的一些经典算法做到逐行分析、多算法比较。与市场上的同类数据结构图书相比,本书内容趣味易读,算法讲解细致深刻,是一本非常适合自学的读物。 本书以一个计算机教师教......一起来看看 《大话数据结构》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具