HNCTF2022 RE

[HNCTF 2022 WEEK2]Try2Bebug_Plus

静态分析

64位ELF,ida打开

主函数

decrypt函数,为tea加密,v ,k 已知

tea加密解密函数(C语言)

#include <stdio.h>
#include <stdint.h>
 
void encrypt (uint32_t *v,uint32_t *k ){
	uint32_t v0=v[0],v1=v[1],sum=0,i;
	uint32_t delta=0x9e3779b9;
	uint32_t k0=k[0],k1=k[1],k2=k[2],k3=k[3];
	for(i=0;i<32;i++){
		sum+=delta;
		v0+=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
		v1+=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
	} 
	v[0]=v0;v[1]=v1;
}
void decrypt (uint32_t *v,uint32_t *k){
	uint32_t v0=v[0],v1=v[1],sum=0xC6EF3720,i;	//这里的sum是0x9e3779b9*32后截取32位的结果,截取很重要。
	uint32_t delta=0x9e3779b9;
	uint32_t k0=k[0],k1=k[1],k2=k[2],k3=k[3];
	for (i=0;i<32;i++){
		v1-=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);
		v0-=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);
		sum-=delta;
	} 
	v[0]=v0;v[1]=v1;
}
 
int main()
{
	uint32_t v[2]={1,2},k[4]={2,2,3,4};
	printf("加密前的数据:%u %u\n",v[0],v[1]);	//%u 以十进制形式输出无符号整数 
	encrypt(v,k);
	printf("加密后数据:%u %u\n",v[0],v[1]);
	decrypt(v,k);
	printf("解密后数据:%u %u\n",v[0],v[1]);
	return 0;
}

function函数

根据以上写脚本即可,不用逆向,直接写

#include <stdio.h>
#include <stdint.h>
#include<string.h>

void decrypt(unsigned int *v, int *a2)
{
  
  unsigned int v0; // [rsp+1Ch] [rbp-24h]
  unsigned int v1; // [rsp+20h] [rbp-20h]
  unsigned int sum; // [rsp+24h] [rbp-1Ch]
  unsigned int i; // [rsp+28h] [rbp-18h]

  v0 = *v;
  v1 = v[1];
  sum = 0xC6EF3720;
  for ( i = 0; i <= 31; ++i )
  {
    v1 -= (v0 + sum) ^ (16 * v0 + a2[2]) ^ ((v0 >> 5) + a2[3]);
    v0 -= (v1 + sum) ^ (16 * v1 + *a2) ^ ((v1 >> 5) + a2[1]);
    sum += 0x61C88647;
  }
  *v = v0;

  v[1] = v1;
 
}



 
int main()
{
	unsigned int v[12]={0x489A0BFD, 0x38DE3838, 0x16D1DA51, 0x710510ED, 0x1E619392, 0x0B487955, 0x0AB44987, 0x5DB378E5, 0x9F9DA4CD,0x49F2D9A8, 0x608F269E, 0x6261B831};
	int k[4]={0xAA, 0xBB, 0xCC, 0xDD};
	unsigned char v3[12];
	int i;
	 for ( i = 0; i <= 11; i=i + 2 )
    	decrypt(&v[i], k);
	for ( i = 0; i <= 11; ++i )
    {
    	v3[i] = (16 * i) ^ v[i];//v是整型,占四个字节 
    	printf("%c",v3[i]);
	}
	//th1s_1s_flag
	return 0;
}

动态调试-learn

[HNCTF 2022 WEEK4]ez_maze

python 逆向

 打开maze.pyc在生成的文件夹下面

添加前面的字节码

打开winhex--编辑--粘贴0字节--11,修改前面的部分即可

观察发现python3.9版本的,找在线网站转成py

崩溃啦...

[HNCTF 2022 WEEK3]What's 1n DLL?

题目提示有壳,给了两个文件

改一下特征值,但是中间有一段全是0,有点奇怪

然后脱壳

DDL里面看ttt函数,看出来应该是xxtea加密

看task函数

enc dd 22A577C1h, 1C12C03h, 0C74C3EBDh, 0A9D03C85h, 0ADB8FFB3h

这里用 LoadLibrary 加载了一个名为Dll1.dll的动态链接库,这个函数会返回一个模块的句柄hModule。之后用 GetProcAddress函数来获取DLL中某个导出函数的地址,在这里就是,加载Dll1.dll,来获取其中名为ttt的函数地址,之后将其保存在ProcAddress变量中。

因此我们直接去逆Dll1.dll就好。

LoadLibrary 函数
[格式]:

function LoadLibrary(LibFileName : PChar): Thandle;
[功能]:加载由参数 LibFileName 指定的 DLL 文件。

[说明]:参数 LibFileName 指定了要装载的 DLL 文件名,如果 LibFileName 没有包含一个路径,系统将按照:当前目录、Windows 目录、Windows 系统目录、包含当前任务可执行文件的目录、列在 PATH 环境变量中的目录等顺序查找文件。

如果函数操作成功,将返回装载 DLL 库模块的实例句柄,否则,将返回一个错误代码,错误代码的定义如引文[1]所示。

GetProcAddress 函数
[格式]:

function GetProcAddress(Module:Thandle; ProcName:PChar): TfarProc;
[功能]:返回参数 Module 指定的模块中,由参数 ProcName 指定的过程或函数的入口地址。

[说明]:参数 Module 包含被调用函数的 DLL 句柄,这个值由 LoadLibrary 返回, ProcName
是指向含有函数名的以 nil 结尾的字符串指针,或者可以是函数的次序值,但大多数情况下,用函数名是一种更稳妥的选择。如果该函数执行成功,则返回 DLL 中由参数 ProcName 指定的过程或函数的入口地址,否则返回 nil 

exp

#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)))
#define uint32_t unsigned int

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[]= {0x22A577C1, 0x1C12C03, 0x0C74C3EBD,0x0A9D03C85, 0x0ADB8FFB3};
        uint32_t const k[4]= {55,66,77,88};
        int n= 5; //n的绝对值表示v的长度,取正表示加密,取负表示解密
        // v为要加密的数据是两个32位无符号整数
        // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
        // 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("解密后的数据:");
        char *p=(char *) v;
        for(int i=0;i<20;i++){
          printf("%c",*p);
          p++;}

        
        
        return 0;
}                                                                    

xxtea找个脚本解密

#include <stdbool.h>
#include <stdio.h>
#define MX ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))
bool btea(unsigned int* v, int n, unsigned int* k) {
  unsigned int z = v[n - 1], y = v[0], sum = 0, e, DELTA = 0x9e3779b9;
  unsigned int p, q;
  if (n > 1) { /* Coding Part */
    q = 6 + 52 / n;
    while (q-- > 0) {
      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;
    }
    return 0;
  } else if (n < -1) { /* Decoding Part */
    n = -n;
    q = 6 + 52 / n;
    sum = q * DELTA;
    while (sum != 0) {
      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;
    }
    return 0;
  }
  return 1;
}
 
int main(int argc, char const* argv[]) {
  unsigned int v[5] = {0x22a577c1,0x1c12c03,0xc74c3ebd,0xa9d03c85,0xadb8ffb3}, key[4] = {55,66,77,88};
  int n = 5;         //n为要加密的数据个数
  btea(v, -n, key);         // 取正为加密,取负为解密
  char *p=(char *) v;
	for(int i=0;i<20;i++){
		printf("%c",*p);
		p++;
	}
  return 0;
}

// NSSCTF{He110_w0r1d!} 

  • 15
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值