ciscn2022 re-babycode复现

使用mruby生成字节码

./mruby -v babycode.mrb 
mruby 3.1.0 (2022-05-12)
irep 0x55a0b4a19dc0 nregs=5 nlocals=2 pools=1 syms=5 reps=2 ilen=55
local variable names:
  R1:p
      000 LOADNIL	R2		
      002 LOADNIL	R3		
      004 CLASS		R2	:Crypt
      007 EXEC		R2	I(0:0x55a0b4a19e70)
      010 TCLASS	R2		
      
	  012 METHOD	R3	I(1:0x55a0b4a1a670)
      015 DEF		R2	:check
	  
      018 SSEND		R2	:gets	n=0
      022 SEND		R2	:chomp	n=0
      026 MOVE		R1	R2		; R1:p
      029 MOVE		R3	R1		; R1:p
      032 SSEND		R2	:check	n=1
      036 JMPNOT	R2	050	
      040 STRING	R3	L(0)	; yes
      043 SSEND		R2	:puts	n=1
      047 JMP		052
      050 LOADNIL	R2		
      052 RETURN	R2		
      054 STOP
	  
//Crypt 的构造函数???
irep 0x55a0b4a19e70 nregs=3 nlocals=1 pools=0 syms=1 reps=1 ilen=12
      000 LOADNIL	R1		
      002 LOADNIL	R2		
      004 CLASS		R1	:CIPHER
      007 EXEC		R1	I(0:0x55a0b4a19f40)
      010 RETURN	R1		

//
irep 0x55a0b4a19f40 nregs=3 nlocals=1 pools=0 syms=6 reps=4 ilen=55
      000 LOADI32	R1	305419896	
      006 SETCONST	XX	R1	
      009 LOADI		R1	16	
      012 SETCONST	YY	R1	
	  
	  
      015 LOADSELF	R1		
      017 SCLASS		R1	
      019 METHOD	R2	I(0:0x55a0b4a1a080)
      022 DEF		R1	:encrypt
	  
	  //这些是私有的🐎????
      025 TCLASS	R1		
      027 METHOD	R2	I(1:0x55a0b4a1a120)
      030 DEF		R1	:encrypt
	  
      033 SSEND		R1	:private	n=0
      
	  037 TCLASS	R1		
      039 METHOD	R2	I(2:0x55a0b4a1a440)
      042 DEF		R1	:to_key
     
	 045 TCLASS	R1		
      047 METHOD	R2	I(3:0x55a0b4a1a510)
      050 DEF		R1	:enc_one
      053 RETURN	R1		


//encrypt 函数
irep 0x55a0b4a1a080 nregs=9 nlocals=5 pools=0 syms=3 reps=0 ilen=29
local variable names:
  R1:t
  R2:p
  R3:&
  R4:cip
      000 ENTER		2:0:0:0:0:0:0 (0x80000)
      004 GETCONST	R5	CIPHER	
      007 SEND		R5	:new	n=0
      011 MOVE		R4	R5		; R4:cip
      014 MOVE		R5	R4		; R4:cip
      017 MOVE		R6	R1		; R1:t
      020 MOVE		R7	R2		; R2:p
      023 SEND		R5	:encrypt	n=2
      027 RETURN	R5		


//encrypt 函数
irep 0x55a0b4a1a120 nregs=16 nlocals=11 pools=1 syms=8 reps=1 ilen=346
local variable names:
  R1:t
  R2:p
  R3:&
  R4:key
  R5:c
  R6:n
  R7:num1
  R8:num2
  R9:enum1
  R10:enum2
      000 ENTER		2:0:0:0:0:0:0 (0x80000)
	  //
      004 MOVE		R12	R2		; R2:p
      007 SSEND		R11	:to_key	n=1
      011 MOVE		R4	R11		; R4:key
      014 ARRAY		R5	R5	0	; R5:c
      017 LOADI_0	R6			; R6:n
      019 MOVE		R11	R6		; R6:n
      022 MOVE		R12	R1		; R1:t
      025 SEND		R12	:length	n=0
      029 LT		R11	R12
      031 JMPNOT	R11	327	
	  //loop 
      035 MOVE		R11	R1		; R1:t
      038 MOVE		R12	R6		; R6:n
      041 GETIDX	R11	R12
      043 SEND		R11	:ord	n=0
      047 SEND		R11	:to_i	n=0
      051 LOADI		R12	24	
      054 SEND		R11	:<<	n=1
      058 MOVE		R7	R11		; R7:num1
      061 MOVE		R11	R7		; R7:num1
	  //
      064 MOVE		R12	R1		; R1:t
      067 MOVE		R13	R6		; R6:n
      070 ADDI		R13	1	
      073 GETIDX	R12	R13
      075 SEND		R12	:ord	n=0
      079 SEND		R12	:to_i	n=0
      083 LOADI		R13	16	
      086 SEND		R12	:<<	n=1
      090 ADD		R11	R12
      092 MOVE		R7	R11		; R7:num1
      095 MOVE		R11	R7		; R7:num1
	  //
      098 MOVE		R12	R1		; R1:t
      101 MOVE		R13	R6		; R6:n
      104 ADDI		R13	2	
      107 GETIDX	R12	R13
      109 SEND		R12	:ord	n=0
      113 SEND		R12	:to_i	n=0
      117 LOADI		R13	8	
      120 SEND		R12	:<<	n=1
      124 ADD		R11	R12
      126 MOVE		R7	R11		; R7:num1
      129 MOVE		R11	R7		; R7:num1
	  //
      132 MOVE		R12	R1		; R1:t
      135 MOVE		R13	R6		; R6:n
      138 ADDI		R13	3	
      141 GETIDX	R12	R13
      143 SEND		R12	:ord	n=0
      147 SEND		R12	:to_i	n=0
      151 ADD		R11	R12
      153 MOVE		R7	R11		; R7:num1
	  //
	  
      156 MOVE		R11	R1		; R1:t
      159 MOVE		R12	R6		; R6:n
      162 ADDI		R12	4	
      165 GETIDX	R11	R12
      167 SEND		R11	:ord	n=0
      171 SEND		R11	:to_i	n=0
      175 LOADI		R12	24	
      178 SEND		R11	:<<	n=1
      182 MOVE		R8	R11		; R8:num2
      185 MOVE		R11	R8		; R8:num2
      188 MOVE		R12	R1		; R1:t
      191 MOVE		R13	R6		; R6:n
      194 ADDI		R13	5	
      197 GETIDX	R12	R13
      199 SEND		R12	:ord	n=0
      203 SEND		R12	:to_i	n=0
      207 LOADI		R13	16	
      210 SEND		R12	:<<	n=1
      214 ADD		R11	R12
      216 MOVE		R8	R11		; R8:num2
      219 MOVE		R11	R8		; R8:num2
	  
      222 MOVE		R12	R1		; R1:t
      225 MOVE		R13	R6		; R6:n
      228 ADDI		R13	6	
      231 GETIDX	R12	R13
      233 SEND		R12	:ord	n=0
      237 SEND		R12	:to_i	n=0
      241 LOADI		R13	8	
      244 SEND		R12	:<<	n=1
      248 ADD		R11	R12
      250 MOVE		R8	R11		; R8:num2
      253 MOVE		R11	R8		; R8:num2
	  //
      256 MOVE		R12	R1		; R1:t
      259 MOVE		R13	R6		; R6:n
      262 ADDI		R13	7	
      265 GETIDX	R12	R13
      267 SEND		R12	:ord	n=0
      271 SEND		R12	:to_i	n=0
      275 ADD		R11	R12
      277 MOVE		R8	R11		; R8:num2
	  //
	  
	  
	  //enc_one(num1,num2,key)
      280 MOVE		R12	R7		; R7:num1
      283 MOVE		R13	R8		; R8:num2
      286 MOVE		R14	R4		; R4:key
      289 SSEND		R11	:enc_one	n=3
      
	  // 结果附加到数组末尾。
	  //arr = arr << num1
	  //arr = arr << num2
	  293 AREF		R9	R11	0	; R9:enum1
      297 AREF		R10	R11	1	; R10:enum2
      301 MOVE		R11	R5		; R5:c
      304 MOVE		R12	R9		; R9:enum1
      307 SEND		R11	:<<	n=1
      311 MOVE		R11	R5		; R5:c
      314 MOVE		R12	R10		; R10:enum2
      317 SEND		R11	:<<	n=1
	  //
      321 ADDI		R6	8		; R6:n
      324 JMP		019
	  
	  //生成字符串, enc_str = arr.collect{|x| sprintf("%.8x",x)}.join("")
      327 MOVE		R11	R5		; R5:c
      330 BLOCK		R12	I(0:0x55a0b4a1a370)
      333 SENDB		R11	:collect	n=0
      337 STRING	R12	L(0)	; 
      340 SEND		R11	:join	n=1
      344 RETURN	R11		

irep 0x55a0b4a1a370 nregs=7 nlocals=3 pools=1 syms=1 reps=0 ilen=16
local variable names:
  R1:x
  R2:&
      000 ENTER		1:0:0:0:0:0:0 (0x40000)
      004 STRING	R4	L(0)	; %.8x
      007 MOVE		R5	R1		; R1:x
      010 SSEND		R3	:sprintf	n=2
      014 RETURN	R3		

//to key......
//"aaaassssddddffff" ----> [1633771873, 1936946035, 1684300900, 1717986918] 
irep 0x55a0b4a1a440 nregs=6 nlocals=3 pools=1 syms=1 reps=0 ilen=16
local variable names:
  R1:p
  R2:&
      000 ENTER		1:0:0:0:0:0:0 (0x40000)
      004 MOVE		R3	R1		; R1:p
      007 STRING	R4	L(0)	; L*
      010 SEND		R3	:unpack	n=1
      014 RETURN	R3		

//
irep 0x55a0b4a1a510 nregs=11 nlocals=8 pools=0 syms=2 reps=1 ilen=42
local variable names:
  R1:num1
  R2:num2
  R3:key
  R4:&
  R5:y
  R6:z
  R7:s
      000 ENTER		3:0:0:0:0:0:0 (0xc0000)
      004 MOVE		R8	R1		; R1:num1
      007 MOVE		R9	R2		; R2:num2
      010 LOADI_0	R10		
	  /*
			y = num1
			z = num2
			r3 = key
			s = delta.
	  */
      012 MOVE		R5	R8		; R5:y
      015 MOVE		R6	R9		; R6:z
      018 MOVE		R7	R10		; R7:s
	  /*
			16.times do
				tea_encrypt_xxx()
			end
	  */
      021 GETCONST	R8	YY	
      024 BLOCK		R9	I(0:0x55a0b4a1a5e0)
      027 SENDB		R8	:times	n=0
	  
      031 MOVE		R8	R5		; R5:y
      034 MOVE		R9	R6		; R6:z
	  
      037 ARRAY		R8	R8	2
	  // return {y,z};
      040 RETURN	R8		

irep 0x55a0b4a1a5e0 nregs=10 nlocals=3 pools=1 syms=5 reps=0 ilen=186
local variable names:
  R1:i
  R2:&
      000 ENTER		1:0:0:0:0:0:0 (0x40000)
	  
      004 GETUPVAR	R3	5	0	
      008 GETUPVAR	R4	6	0	
      012 LOADI_3	R5		
      014 SEND		R4	:<<	n=1
      018 GETUPVAR	R5	6	0	
      022 LOADI_5	R6		
      024 SEND		R5	:>>	n=1
      028 SEND		R4	:^	n=1
	  
      032 GETUPVAR	R5	6	0	
      036 ADD		R4	R5
	  
	  ///
      038 GETUPVAR	R5	7	0	
      042 GETUPVAR	R6	3	0	
      046 GETUPVAR	R7	7	0	
      050 LOADI		R8	11	
      053 SEND		R7	:>>	n=1
      057 ADDI		R7	1	
      060 LOADI_3	R8		
      062 SEND		R7	:&	n=1
      066 GETIDX	R6	R7
      068 ADD		R5	R6
	  
      070 SEND		R4	:^	n=1
      074 ADD		R3	R4
      076 SETUPVAR	R3	5	0	
	  //
      080 LOADL		R4	L(0)	; 4294967295
      083 SEND		R3	:&	n=1
      087 SETUPVAR	R3	5	0	
	  //
	  //delta += XX
      091 GETUPVAR	R3	7	0	
      095 GETCONST	R4	XX	
      098 ADD		R3	R4
      100 SETUPVAR	R3	7	0	
	  
	  //
      104 GETUPVAR	R3	6	0	
      108 GETUPVAR	R4	5	0	
      112 LOADI_3	R5		
      114 SEND		R4	:<<	n=1
      118 GETUPVAR	R5	5	0	
      122 LOADI_5	R6		
      124 SEND		R5	:>>	n=1
      128 SEND		R4	:^	n=1
      132 GETUPVAR	R5	5	0	
      136 ADD		R4	R5
      138 GETUPVAR	R5	7	0	
      142 GETUPVAR	R6	3	0	
      146 GETUPVAR	R7	7	0	
      150 ADDI		R7	1	
      153 LOADI_3	R8		
      155 SEND		R7	:&	n=1
      159 GETIDX	R6	R7
      161 ADD		R5	R6
      163 SEND		R4	:^	n=1
      167 ADD		R3	R4
      169 SETUPVAR	R3	6	0	
      173 LOADL		R4	L(0)	; 4294967295
      176 SEND		R3	:&	n=1
      180 SETUPVAR	R3	6	0	
      184 RETURN	R3		


//check 函数
//check(flag)

irep 0x55a0b4a1a670 nregs=13 nlocals=8 pools=2 syms=7 reps=0 ilen=128
local variable names:
  R1:p
  R2:&
  R3:i
  R4:lst_ch
  R5:c
  R6:k
  R7:cipher_text
      000 ENTER		1:0:0:0:0:0:0 (0x40000)
      004 LOADI_0	R3			; R3:i
      006 LOADI_0	R4			; R4:lst_ch
      008 MOVE		R8	R3		; R3:i
      011 MOVE		R9	R1		; R1:p ,
      014 SEND		R9	:length	n=0
      018 LT		R8	R9
      020 JMPNOT	R8	086	
	  
	  //body 
      024 MOVE		R8	R1		; R1:p
      027 MOVE		R9	R3		; R3:i
      030 GETIDX	R8	R9
      032 SEND		R8	:ord	n=0
	  //temp = data[i]
      036 MOVE		R5	R8		; R5:c
      039 MOVE		R8	R5		; R5:c
      042 MOVE		R9	R4		; R4:lst_ch
      045 SEND		R8	:^	n=1
      049 MOVE		R9	R3		; R3:i
      052 ADDI		R9	1	
      055 SEND		R8	:^	n=1
	  059 SEND		R8	:chr	n=0
      //data[i] = (data[i] ^ last_ch) ^ (i + 1)
	  063 MOVE		R9	R1		; R1:p
      066 MOVE		R10	R3		; R3:i
      069 MOVE		R11	R8	
      072 SETIDX	R9	R10	R11
	  //last_ch = temp
      074 MOVE		R8	R5		; R5:c
      077 MOVE		R4	R8		; R4:lst_ch
      080 ADDI		R3	1		; R3:i
      083 JMP		008
	  //
      086 STRING	R6	L(0)	; aaaassssddddffff	; R6:k
      089 GETCONST	R8	Crypt	
      092 GETMCNST	R8	R8::CIPHER	
      095 MOVE		R9	R1		; R1:p
      098 MOVE		R10	R6		; R6:k
	  /*
					encrypt(self,data,key)
	  */
      101 SEND		R8	:encrypt	n=2		
      105 MOVE		R7	R8		; R7:cipher_text
      108 MOVE		R8	R7		; R7:cipher_text
      111 STRING	R9	L(1)	; f469358b7f165145116e127ad6105917bce5225d6d62a714c390c5ed93b22d8b6b102a8813488fdb
      114 EQ		R8	R9
      116 JMPNOT	R8	124	
      120 LOADT		R8		
      122 RETURN	R8		
      124 LOADF		R8		
      126 RETURN	R8		


里面的字节码自行google

正向和逆向的c代码:

#include <stdio.h>
#include <string.h>
#include <string>
using namespace std;

unsigned char szKey[] = "aaaassssddddffff";
char g_szFlag[256] = { 0 };

unsigned int XX = 305419896;
unsigned int YY = 16;

unsigned int enc_data[10] = { 0 };

void dec_one(unsigned int&num1, unsigned int&num2, unsigned int *key){
	unsigned long long delta = 0;
	unsigned int t = 0;

	for (int j = 0; j < 16; j++){
		delta += XX;
	}
	//
	for (int j = 0; j < 16; j++){
		t = (((num1 << 3) ^ (num1 >> 5)) + num1) ^ (delta + key[(delta + 1) & 3]);
		num2 -= t;

		delta -= XX;
		//
		t = (((num2 << 3) ^ (num2 >> 5)) + num2) ^ (delta + key[((delta >> 11) + 1) & 3]);
		num1 -= t;
	}
}

void enc_one(unsigned int&num1,unsigned int&num2,unsigned int*key){
	
	unsigned long long delta = 0;

	for (int i = 0; i < 1; i++){
			unsigned int t1 = 0;
			unsigned int t2 = 0;

			t1 = (((num2 << 3) ^ (num2 >> 5)) + num2) ^ (delta + key[((delta >> 11) + 1) & 3]);
			num1 += t1;
			delta += XX;
			t2 = (((num1 << 3) ^ ( num1 >> 5)) + num1) ^  (delta + key[(delta + 1) & 3]);
			num2 += t2;

	}
}

void encrypt(unsigned char*data,int len,unsigned int* key){
	
	for (int i = 0,j = 0; i < len; i += 8,j++){
		//改变字节序
		unsigned int t = 0;
		unsigned int num1, num2;
		t = *(unsigned int*)&data[i];
		num1 =(((t & 0xff) << 24) | ((t & 0xff00) << 8) | ((t & 0xff0000) >> 8) | ((t & 0xff000000) >> 24));
		//num1 = t;
		t = *(unsigned int*)&data[i + 4];
		num2 = (((t & 0xff) << 24) | ((t & 0xff00) << 8) | ((t & 0xff0000) >> 8) | ((t & 0xff000000) >> 24));
		//num2 = t;
		enc_one(num1, num2, key);
		//
		enc_data[j * 2 + 0] = num1;
		enc_data[j * 2 + 1] = num2;
	}
}

void check(char*flag){

	int len = strlen(flag);
	unsigned char last_ch = 0;

	for (int i = 0; i < len; i++){
		unsigned char t = flag[i];
		unsigned char r8 = flag[i];
		r8 = (r8 ^ last_ch) ^ (i + 1);
		flag[i] = r8;
		last_ch = t;
	}

	encrypt((unsigned char*)flag, len,(unsigned int*)szKey);

	if (!strcmp(g_szFlag, "f469358b7f165145116e127ad6105917bce5225d6d62a714c390c5ed93b22d8b6b102a8813488fdb")){
		printf("OK!");
		return;
	}
}

char enc[] = "f469358b7f165145116e127ad6105917bce5225d6d62a714c390c5ed93b22d8b6b102a8813488fdb";

void decode(unsigned int *key){
	//
	unsigned int arr[11] = { 0 };
	unsigned char*p = NULL;

	/*for (int i = 0; i < 10; i++){
		arr[i] = enc_data[i];
	}*/
	for (int i = 0; i < 10; i ++)
	{
		char buff[12] = { 0 };
		unsigned int val = 0;
		memcpy(buff, enc + i*8, 8);
		
		sscanf(buff, "%x", &val);
		arr[i] = val;
	}
	
	for (int i = 0; i < 5; i++){
		unsigned int num1 = arr[i * 2 + 0];
		unsigned int num2 = arr[i * 2 + 1];
		unsigned int t = 0;

		dec_one(num1, num2, (unsigned int*)szKey);

		//交换字节序
		t = num1;
		num1 = (((t & 0xff) << 24) | ((t & 0xff00) << 8) | ((t & 0xff0000) >> 8) | ((t & 0xff000000) >> 24));
		t = num2;
		num2 = (((t & 0xff) << 24) | ((t & 0xff00) << 8) | ((t & 0xff0000) >> 8) | ((t & 0xff000000) >> 24));
		//
		arr[i * 2 + 0] = num1;
		arr[i * 2 + 1] = num2;
	}

	//tea decrypt
	//
	p = (unsigned char*)arr;
	unsigned char last_ch = 0;

	for (int i = 0; i < 40; i++){
		p[i] = (p[i] ^ last_ch) ^ (i + 1);
		last_ch = p[i];
	}
	//
	puts((char*)p);
}

int main()
{
	decode((unsigned int*)szKey);
	return 0;
}

一些需要注意的地方:
Ruby 的<<作用于数组是append到数组末尾

enc_one进行了 YY (16次) 类似tea 的加密操作,每次enc_one之后将两个数字添加到结果数组

将enc最后的到的数组 对每一个元素 进行 sprintf 生成16进制字符串,最后把这些字符串拼接起来

to_key 和 C语言里面(unsigned int*)szKey 一样

enc_one里面 (num<<3) ^ (num>>5) 中间是异或,由于是int32(不是uint8),不能换成 or

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Suspend.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值