2021-hgame-apache XXTEA算法的小题目

前言:XXTEA算法的一道例题,仅仅是学习记录笔记

链接:https://pan.baidu.com/s/1H9jq_VoynN5_2rS3Kh205A
提取码:0syj

程序分析

call sub_559BB24A4447的作用:使用XXTEA加密输入的字符串

CALL sub_559BB24A4550的作用:验证加密字符串与设定字符串是否相等

XXTEA算法识别0x9E3779B8,如下图所示

XXTEA四个无符号整形密钥,如下图所示

整体汇编分析

.text:0000559BB24A459E     ; int __fastcall main(int, char **, char **)
.text:0000559BB24A459E     main            proc near               ; DATA XREF: start+21↑o
.text:0000559BB24A459E
.text:0000559BB24A459E     var_48          = dword ptr -48h
.text:0000559BB24A459E     var_44          = dword ptr -44h
.text:0000559BB24A459E     var_40          = dword ptr -40h
.text:0000559BB24A459E     var_3C          = dword ptr -3Ch
.text:0000559BB24A459E     var_38          = byte ptr -38h
.text:0000559BB24A459E     var_10          = qword ptr -10h
.text:0000559BB24A459E
.text:0000559BB24A459E     ; __unwind {
.text:0000559BB24A459E     ;   __unwind {
.text:0000559BB24A459E 000                 push    rbx
.text:0000559BB24A459F 008                 sub     rsp, 40h
.text:0000559BB24A45A3 048                 mov     rax, fs:28h
.text:0000559BB24A45AC 048                 mov     [rsp+48h+var_10], rax
.text:0000559BB24A45B1 048                 xor     eax, eax
.text:0000559BB24A45B3 048                 mov     [rsp+48h+var_48], 1 ; 4个无符号整型的密钥
.text:0000559BB24A45BA 048                 mov     [rsp+48h+var_44], 2
.text:0000559BB24A45C2 048                 mov     [rsp+48h+var_40], 3
.text:0000559BB24A45CA 048                 mov     [rsp+48h+var_3C], 4
.text:0000559BB24A45D2 048                 call    print_cup       ; 打印logo
.text:0000559BB24A45D7 048                 lea     rsi, aPleaseInput ; "Please input: "
.text:0000559BB24A45DE 048                 mov     edi, 1
.text:0000559BB24A45E3 048                 mov     eax, 0
.text:0000559BB24A45E8 048                 call    ___printf_chk   ; 打印
.text:0000559BB24A45ED 048                 lea     rbx, [rsp+48h+var_38]
.text:0000559BB24A45F2 048                 mov     rsi, rbx
.text:0000559BB24A45F5 048                 lea     rdi, a35s       ; "%35s"
.text:0000559BB24A45FC 048                 mov     eax, 0
.text:0000559BB24A4601 048                 call    ___isoc99_scanf ; scanf
.text:0000559BB24A4606 048                 mov     rcx, 0FFFFFFFFFFFFFFFFh ; ecx = -1
.text:0000559BB24A460D 048                 mov     eax, 0          ; eax = 输入的字符串长度
.text:0000559BB24A4612 048                 mov     rdi, rbx        ; rdi = 输入的字符串地址
.text:0000559BB24A4615 048                 repne scasb
.text:0000559BB24A4617 048                 mov     rax, rcx
.text:0000559BB24A461A 048                 not     rax
.text:0000559BB24A461D 048                 cmp     eax, 24h        ; 判断输入的字符串长度是否为36
.text:0000559BB24A4620 048                 jz      short loc_559BB24A4638
.text:0000559BB24A4622 048                 lea     rdi, aWrongLength ; "wrong length!"
.text:0000559BB24A4629 048                 call    _puts
.text:0000559BB24A462E 048                 mov     edi, 0          ; status
.text:0000559BB24A4633 048                 call    _exit
.text:0000559BB24A4638     ; ---------------------------------------------------------------------------
.text:0000559BB24A4638
.text:0000559BB24A4638     loc_559BB24A4638:                       ; CODE XREF: main+82↑j
.text:0000559BB24A4638 048                 mov     edi, 8Ch        ; size
.text:0000559BB24A463D 048                 call    _malloc         ; 申请0x8c大小空间
.text:0000559BB24A4642 048                 mov     rbx, rax        ; rbx = 申请空间的地址
.text:0000559BB24A4645 048                 mov     eax, 0
.text:0000559BB24A464A 048                 lea     rcx, [rsp+48h+var_38] ; rcx = 输入的字符串地址
.text:0000559BB24A464F
.text:0000559BB24A464F     loc_559BB24A464F:                       ; CODE XREF: main+C0↓j
.text:0000559BB24A464F 048                 movsx   edx, byte ptr [rax+rcx]
.text:0000559BB24A4653 048                 mov     [rbx+rax*4], edx ; 将输入的字符串拷贝到新申请的0x8c的地址中
.text:0000559BB24A4656 048                 add     rax, 1
.text:0000559BB24A465A 048                 cmp     rax, 23h
.text:0000559BB24A465E 048                 jnz     short loc_559BB24A464F ; 拷贝
.text:0000559BB24A4660 048                 mov     rdx, rsp        ; rdx = 栈顶
.text:0000559BB24A4663 048                 mov     esi, 23h        ; 字符串长度
.text:0000559BB24A4668 048                 mov     rdi, rbx        ; 存放输入的字符串
.text:0000559BB24A466B 048                 call    sub_559BB24A4447 ; 使用XXTEA加密输入的字符串
.text:0000559BB24A4670 048                 mov     esi, 23h
.text:0000559BB24A4675 048                 mov     rdi, rbx
.text:0000559BB24A4678 048                 call    sub_559BB24A4550 ; 验证加密完的字符串是否跟程序本身要判断的相等
.text:0000559BB24A467D 048                 test    eax, eax        ; eax存储判断完的返回值
.text:0000559BB24A467F 048                 jnz     short loc_559BB24A46A8
.text:0000559BB24A4681 048                 lea     rdi, aTryAgain  ; "    :(  Try again."
.text:0000559BB24A4688 048                 call    _puts
.text:0000559BB24A468D
.text:0000559BB24A468D     loc_559BB24A468D:                       ; CODE XREF: main+116↓j
.text:0000559BB24A468D 048                 mov     eax, 0
.text:0000559BB24A4692 048                 mov     rsi, [rsp+48h+var_10]
.text:0000559BB24A4697 048                 xor     rsi, fs:28h
.text:0000559BB24A46A0 048                 jnz     short loc_559BB24A46B6
.text:0000559BB24A46A2 048                 add     rsp, 40h
.text:0000559BB24A46A6 008                 pop     rbx
.text:0000559BB24A46A7 000                 retn
.text:0000559BB24A46A8     ; ---------------------------------------------------------------------------
.text:0000559BB24A46A8
.text:0000559BB24A46A8     loc_559BB24A46A8:                       ; CODE XREF: main+E1↑j
.text:0000559BB24A46A8 048                 lea     rdi, aFlagIsYourInpu ; "    :)  Flag is your input."
.text:0000559BB24A46AF 048                 call    _puts

算法逆向编写

#include <stdio.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))

void btea(uint32_t *v, int n, uint32_t const key[4])
{
	uint32_t y, z, sum;
	unsigned p, rounds, e;
	if (n > 1)            /* Coding Part */
	{
		rounds = 6 + 52 / n;
		sum = 0;
		z = v[n - 1];
		do
		{
			sum += DELTA;
			e = (sum >> 2) & 3;
			for (p = 0; p<n - 1; p++)
			{
				y = v[p + 1];
				z = v[p] += MX;
			}
			y = v[0];
			z = v[n - 1] += MX;
		} while (--rounds);
	}
	else if (n < -1)      /* Decoding Part */
	{
		n = -n;
		rounds = 6 + 52 / n;
		sum = rounds*DELTA;
		y = v[0];
		do
		{
			e = (sum >> 2) & 3;
			for (p = n - 1; p>0; p--)
			{
				z = v[p - 1];
				y = v[p] -= MX;
			}
			z = v[n - 1];
			y = v[0] -= MX;
			sum -= DELTA;
		} while (--rounds);
	}
}


int main()
{
	uint32_t v[] = {
		0xE74EB323, 0x0B7A72836, 0x59CA6FE2, 0x967CC5C1, 0xE7802674,
		0x3D2D54E6, 0x8A9D0356, 0x99DCC39C, 0x7026D8ED, 0x6A33FDAD,
		0xF496550A, 0x5C9C6F9E, 0x1BE5D04C, 0x6723AE17, 0x5270A5C2,
		0xAC42130A, 0x84BE67B2, 0x705CC779, 0x5C513D98, 0x0FB36DA2D,
		0x22179645, 0x5CE3529D, 0xD189E1FB, 0xE85BD489, 0x73C8D11F,
		0x54B5C196, 0xB67CB490, 0x2117E4CA, 0x9DE3F994, 0x2F5AA1AA,
		0xA7E801FD, 0xC30D6EAB, 0x1BADDC9C, 0x3453B04A, 0x92A406F9 };
	uint32_t const k[4] = { 1, 2, 3, 4 }; 	// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
	int n = -35; //n的绝对值表示v的长度,取正表示加密,取负表示解密
	//printf("加密前原始数据:%u %u\n", v[0], v[1]);
	btea(v, n, k);
	printf("解密后的数据:%u %u\n", v[0], v[1]);
	//btea(v, -n, k);
	//printf("解密后的数据:%u %u\n", v[0], v[1]);
	return 0;
}

flag: hgame{l00ks_1ike_y0uf0Und_th3_t}

posted @ 2022-03-07 17:59  zpchcbd  阅读(267)  评论(0)    收藏  举报