Resever2(题解)

目录

FCTF

FlowerDance

EzSMC

BUU

reverse3

不一样的flag


FCTF

FlowerDance

花指令:一种专门用来迷惑反编译器的指令片段(不影响程序,但会使反汇编器结果出现问题)

经典的花指令有:jmp,call,ret等

详细原理的链接:恶意代码分析实战 第十五章 对抗反汇编 - 简书

解决办法:

  1. 直接分析异常地址处的指令,分辨花指令和有用的数据
  2. 用nop(0x90)填充垃圾数据

具体操作:

  1. 先按U识别为数据
  2. Edit -> Patch program -> change byte
  3. 将E8修改为90(nop指令)
  4. 再按C转为nop指令剩余的如法炮制,全部的花指令nop之后

按P键重新反编译(要点到main那里才行)

然后按空格键回到方块那里(不知道叫什么),再按F5进行反汇编即可

分析伪代码:

可以知道加密操作那么写出对应解密代码即可

注意解密代码编写时key[i % 8]要对应着加密过程的,不能有误

解密代码:

#include <stdio.h>
#include <string.h>
#include <math.h>
int main(){
char v7[8];
	strcpy(v7, "JunkCode");
	char data_1[28];
	memcpy(data_1, "FkbXXL", 6);
  	data_1[6] = 12;
  	memcpy(&data_1[7], "^$iP", 4);
  	data_1[11] = 127;
  	data_1[12] = 100;
  	data_1[13] = 33;
  	data_1[14] = 56;
  	data_1[15] = 112;
  	data_1[16] = 82;
  	data_1[17] = 47;
  	data_1[18] = 62;
  	data_1[19] = 29;
  	data_1[20] = 100;
  	data_1[21] = 35;
  	data_1[22] = 125;
  	data_1[23] = 116;
  	data_1[24] = 74;
  	data_1[25] = 96;
  	data_1[26] = 8;
  	data_1[27] = 74;
  	int j=26;
  	for ( int i = 0; i<27; i++){
    	data_1[i+1] ^= v7[j % 8] ^ data_1[i];//关键
    	j--;
    }
  	puts(data_1);
  	return 0;
}

得到答案:FCTF{S0-be@ut1fUl-f10weRs}

EzSMC

SMC:自修改代码(Self-Modified Code),是一种特殊的代码技术(在运行时修改自身代码,从而使得程序实际行为与反汇编结果不符,同时修改前的代码段数据也肯非合法指令,从而无法被反汇编器识别)

换句话说,SMC是一种额外的加密技术,在不运行的时候,代码里会加密导致反汇编不出来结果,但是在运行的时候会进行解密然后得到结果

通常的两种破解方式:

  1. 根据静态分析结果(分析逻辑)直接修改程序中的二进制文件(阿巴阿巴阿巴,不太懂)
  2. 在动态调试时将解密后的程序从内存中dump下来(就是动态调试的时候可以直接得到解密后的程序)

这题主要考察动态调试(具体调试过程等之后补上,咱就是说回来补上了,主打不落下一点)

SMC基本操作:

  1. 获取函数首地址
  2. 取消目标地址处读写保护属性
  3. 修改代码(这里是异或操作)
  4. 恢复目标地址处读写保护属性

调试过程:

1.首先正常操作(不细讲了),打开文件并进行反汇编即可

2.下断点,选择合适的调试器(这里使用windows 调试),开始调试

3.这是进入调试之后的页面,然后跟进func()函数

4.跟进后,从func()函数的开头一直到main()函数的前面锁定(就是选中func函数那一块),按U键取消加密(感觉像)

5.再选中func函数那一块按C键识别为代码(有时候可能会有弹窗,点击force,强制执行即可)

6.再选中func函数,按P键重新识别函数,再按F5反汇编即可得到解密后的程序

一些快捷键的使用:

按G键:可以进行跳转到函数地址(可以提前记录地址然后跳转,很方便)

Alt+L:可以固定选中,不用担心点一下选中区域就被取消了(也很好用)

shift+e:快速提取数据

这里放出调试完成后的代码:

可以看出flag和一堆数据进行了异或操作,最后的密文是data(这个数据需要跟进去看并提取出来),那么相应的写出解密代码即可。

解密代码:

#include <stdio.h>
#include <string.h>
#include <math.h>
int main(){
    char Str[] =
	{
  		29,  24,  15,  29,  32,   2, 107,  46, 118,  27, 
        41,  62, 118,  45, 104,  41,  34, 118,  48,  21, 
        52,  44, 118,  40,  54,  56, 118,  58,  51,  63, 
        118,  35, 107,  41,  38
	};
	for ( int i = 0; i <= 34; ++i )
    Str[i] ^= 0x31u;
  for ( int j = 0; j <= 34; ++j )
    Str[j] ^= 7u;
  for ( int k = 0; k <= 34; ++k )
    Str[k] ^= 5u;
  for ( int m = 0; m <= 34; ++m )
    Str[m] ^= 0xDu;
  for ( int n = 0; n <= 34; ++n )
    Str[n] ^= 0x67u;
  for ( int ii = 0; ii <= 34; ++ii )
    Str[ii] ^= 0x48u;
  for ( int jj = 0; jj <= 34; ++jj )
    Str[jj] ^= 0x53u;
  for ( int kk = 0; kk <= 34; ++kk )
    Str[kk] ^= 0x50u;
  for ( int mm = 0; mm <= 34; ++mm )
    Str[mm] ^= 0x35u;
  for ( int nn = 0; nn <= 34; ++nn )
    Str[nn] ^= 0x40u;
  for ( int i1 = 0; i1 <= 34; ++i1 )
    Str[i1] ^= 0x44u;
  for ( int i2 = 0; i2 <= 34; ++i2 )
    Str[i2] ^= 0x2Bu;
  for ( int i3 = 0; i3 <= 34; ++i3 )
    Str[i3] ^= 0x2Eu;
  for ( int i4 = 0; i4 <= 34; ++i4 )
    Str[i4] ^= 0x57u;
  for ( int i5 = 0; i5 <= 34; ++i5 )
    Str[i5] ^= 0x5Fu;
  for ( int i6 = 0; i6 <= 34; ++i6 )
    Str[i6] ^= 0x2Cu;
  for ( int i7 = 0; i7 <= 34; ++i7 )
    Str[i7] ^= 0x65u;
  for ( int i8 = 0; i8 <= 34; ++i8 )
    Str[i8] ^= 0x2Fu;
  for ( int i9 = 0; i9 <= 34; ++i9 )
    Str[i9] ^= 1u;
  for ( int i10 = 0; i10 <= 34; ++i10 )
    Str[i10] ^= 0xDu;
  for ( int i11 = 0; i11 <= 34; ++i11 )
    Str[i11] ^= 0x1Eu;
  for ( int i12 = 0; i12 <= 34; ++i12 )
    Str[i12] ^= 0x22u;
  for (int  i13 = 0; i13 <= 34; ++i13 )
    Str[i13] ^= 0x18u;
  for ( int i14 = 0; i14 <= 34; ++i14 )
    Str[i14] ^= 0x2Du;
  for ( int i15 = 0; i15 <= 34; ++i15 )
    Str[i15] ^= 0x5Fu;
  for ( int i16 = 0; i16 <= 34; ++i16 )
    Str[i16] ^= 0x5Fu;
  for ( int i17 = 0; i17 <= 34; ++i17 )
    Str[i17] ^= 0x15u;
  for ( int i18 = 0; i18 <= 34; ++i18 )
    Str[i18] ^= 0x45u;
  for ( int i19 = 0; i19 <= 34; ++i19 )
    Str[i19] ^= 0x53u;
  for ( int i20 = 0; i20 <= 34; ++i20 )
    Str[i20] ^= 0x5Du;
  for (int  i21 = 0; i21 <= 34; ++i21 )
    Str[i21] ^= 0x6Cu;
  for ( int i22 = 0; i22 <= 34; ++i22 )
    Str[i22] ^= 0x24u;
    for ( int i = 0; i <= 34; ++i)
    	printf("%c",Str[i]);
  	return 0;
}

得到答案:FCTF{Y0u-@re-v3ry-kNow-smc-ahd-x0r}

BUU

reverse3

1.首先正常操作(查壳,反汇编出伪代码)

2.对伪代码进行分析(部分的变量名我进行更改了,更好理解)

跟进sub_4110BE加密操作:很复杂的感觉(看了网上的wp才知道这是Base64的加密过程,真的看不懂啊)

跟进Str2:可以得到密文

那么现在就能够知道主要的加密过程:flag--->Base64加密---->然后进行了一个加法操作---->得到密文

那么现在进行反操作即可,Base64解密直接网上找解密器就行

解密代码:

#include <stdio.h>
#include <string.h>
int main(){
	char Str2[]="e3nifIH9b_C@n@dH";
	for ( int j = 0; j < strlen(Str2); ++j )
    	Str2[j] -= j;
    puts(Str2);
	
  	return 0;
}

得到:e2lfbDB2ZV95b3V9

然后Base64解密得到:{i_l0ve_you}

不一样的flag

很明显这是一道迷宫问题

解决问题三要素:地图,起点和终点位置,上下左右的操作符

打开文件(常规操作):

由地图的限制条件可以得到迷宫共有5行(行值一开始是0),那么可以得到地图是5*5

再结合代码可以知道起点在(0,0)处,终点在“#”

由伪代码可得:

移动操作符:1-上,2-下,3-左,4-右

地图

路线就可以直接手动画出:(只是对于简单的迷宫题,复杂的可以套脚本)

那么可以得到答案:flag{222441144222}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值