首页 > 其他分享 >BUUCTF逆向工程第一页部分题目

BUUCTF逆向工程第一页部分题目

时间:2022-11-20 11:38:16浏览次数:66  
标签:逆向 BUUCTF int 99 flag key 第一页 include IDA

BUUCTF逆向工程第一页部分题目

easyre

这题很水,拖进IDA就可以解出来

很明显,flag:flag{this_Is_a_EaSyRe}

reverse1

拖进IDA发现只有这么个东西

所以果断shift+F12从字符串寻找突破口,得到:

跟进可以进入到真正的主程序:

不难发现它将输入和Str2进行比较,并且在前面将Str2中的o变成了0,跟进Str2可以看见:

得到flag:flag{hell0_w0rld}

reverse2

比上一题仁慈,拽进IDA直接可以看代码:

将输入和flag作比较,并在之前把r和i变成1,跟进看见flag是:

得到flag:flag{hack1ng_fo1_fun}

内涵的软件

打开IDA可以看见v5这个抽象的玩意儿:

没错,这货就是答案,flag:flag{49d3c93df25caad81232130f3d2ebfad}
说实话,我不理解这题存在的意义

新年快乐

exeinfoPE告诉我它有壳并且可以使用自带的upx -d解决,所以就解决一下:

在拖入IDA可以看见主程序:

通过我们在小学二年级就学会的代码,可以读出来flag:flag{HappyNewYear!}

xor

拖进IDA可以看见:

它对输入进行了一通异或操作并且与global进行比较,将global提取出来异或回去即可:

#include <iostream>

using namespace std;

int main()
{
    int key[99] = {
  102,  10, 107,  12, 119,  38,  79,  46,  64,  17, 
  120,  13,  90,  59,  85,  17, 112,  25,  70,  31, 
  118,  34,  77,  35,  68,  14, 103,   6, 104,  15, 
   71,  50,  79,   0};
    int i;
    for(i = 32; i >= 1; i--)
    {
    	key[i] ^= key[i-1];
    }
    for(i = 0; i <= 32; i++)
    {
	cout << char(key[i]);
    }
    return 0;
}

得到flag:flag{QianQiuWanDai_YiTongJiangHu}

reverse3

IDA里看见它对输入做了sub_4110BE操作,然后又做了一个简单的加法,最后和Str2比较:

点进sub_4110BE可以看见这么个抽象的东西:

看出这东西是个base64加密,搞一搞:

#include <iostream>

using namespace std;

int main()
{
	int key[99] = {
  101,  51, 110, 105, 102,  73,  72,  57,  98,  95, 
   67,  64, 110,  64, 100,  72};
    int i;
    for(i = 0; i <= 15; i++)
    {
	 key[i] -= i;
	cout << char(key[i]);
    }
    return 0;
}
#include <iostream>
#include <cstring>

using namespace std;

char base64[50];
char base64char[100];

int __cdecl base64_decode(char *base64, char *originChar)
{
  int v2; // eax
  int v3; // eax
  int v4; // eax
  unsigned __int8 temp[4]; // [rsp+23h] [rbp-Dh] BYREF
  unsigned __int8 k; // [rsp+27h] [rbp-9h]
  int j; // [rsp+28h] [rbp-8h]
  int i; // [rsp+2Ch] [rbp-4h]

  i = 0;
  j = 0;
  while ( base64[i] )
  {
    memset(temp, 255, sizeof(temp));
    for ( k = 0; k <= 0x3Fu; ++k )
    {
      if ( base64char[k] == base64[i] )
        temp[0] = k;
    }
    for ( k = 0; k <= 0x3Fu; ++k )
    {
      if ( base64char[k] == base64[i + 1] )
        temp[1] = k;
    }
    for ( k = 0; k <= 0x3Fu; ++k )
    {
      if ( base64char[k] == base64[i + 2] )
        temp[2] = k;
    }
    for ( k = 0; k <= 0x3Fu; ++k )
    {
      if ( base64char[k] == base64[i + 3] )
        temp[3] = k;
    }
    v2 = j++;
    originChar[v2] = (temp[1] >> 4) & 3 | (4 * temp[0]);
    if ( base64[i + 2] == 61 )
      break;
    v3 = j++;
    originChar[v3] = (temp[2] >> 2) & 0xF | (16 * temp[1]);
    if ( base64[i + 3] == 61 )
      break;
    v4 = j++;
    originChar[v4] = temp[3] & 0x3F | (temp[2] << 6);
    i += 4;
  }
  return j;
}

int main()
{
	char de64[50];
	int i;
	strcpy(base64, "e2lfbDB2ZV95b3V9");//密文 
	strcpy(base64char, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=");//秘钥 
	base64_decode(base64, de64); 
	for(i = 0; i <= strlen(base64); i++)
	{
		cout << de64[i];//明文 
	}
	return 0;
}

得到flag:flag{i_l0ve_you}

不一样的flag

拖进IDA看见这个,可以推断是个迷宫题:

在最后可以看到结束条件是走到#

根据整体代码判断v3[25]是用来控制层数的,通过查阅v3的地址(00000035)和v7的地址(0000000C)恰好相差41可以推断最后它用来判断的v7就是v3,因此它的地图长这个样子:

*1111
01000
01010
00010
1111#

得到flag:flag{222441144222}

SimpleRev

打开IDA发现主要的加密在Decry函数中:

前面一段生成了key和text:

这里理论上下断点动调就可以得到最终结果,但是我动调会告诉我出现了一个奇奇怪怪的错误,所以我只好手动生成了,其中.elf采用逆序存储,因此需要反向解析:

#include <iostream>
#include <string.h>

using namespace std;

int main()
{
	long long v9 = 0x776F646168;//hadow
	long long src = 0x534C43444E;//NDCLS
	int i;
	for(i = 0; i <= 4; i++)
	{
		cout << char(*((const char*)&v9 + i));
	}
	cout << endl; 
	for(i = 0; i <= 4; i++)
	{
		cout << char(*((const char*)&src + i));
	}
	return 0;
}

得到
text = "killshadow"
key = "adsfkndcls"
接下来就是依据输入对Str2进行操作:

可以写个深搜找到答案;

#include <iostream>
#include <string.h>

using namespace std;

int main()
{
	string text = "killshadow";
	string key = "adsfkndcls";
	int i, j, k;
	int v5 = key.size();
	int tmp;
	for(i = 0; i <= 9; i++)
	{
		for(j = 65; j <= 122; j++)
		{
			if((j >= 'a' && j <= 'z') || (j >= 'A' && j <= 'Z'))
			{
				tmp = (j - 39 - key[i] + 97) % 26 + 97;
				if(tmp == text[i])
				{
					cout << char(j);
					break;
				}
			}
		}
	}
	return 0;
}

得到flag:flag{KLDQCUDFZO}
其实这个地方很明显每一个大写输入其实都可以用一个小写字母代替,也可以达到相同的效果,这样的输入是efxkwoxzti。但是我不理解这题后续也没有相应的验证部分,为什么可以直接用大写的输入。。。

[GXYCTF2019]luck_guy

这题点进去发现它会根据随机数除以200的余数进行操作:

但是随机数嘛,多半是假的,所以可以猜测一下他会按照case4,case5,case1的顺序运行,考虑到elf的逆序存储,搞一个脚本:

#include <iostream>
#include <string.h>

using namespace std;

int main()
{
	long long a = 0x7F666F6067756369;
	int i;
	char key2[99] = "";
	char key1[99] = "GXY{do_not_";
	for(i = 0; i <= 7; i++)
	{
		key2[i] = char(*((const char*)&a + i));
		if(key2[i] % 2 == 1)
		{
			key2[i] -= 2;
		}
		else
		{
			key2[i]--;
		}
	}
	strcat(key1, key2);
	cout << key1;
	return 0;
}

得到flag:flag{do_not_gase_me}

[BJDCTF2020]JustRE

拖进IDA里看见代码很抽象,所以shift+F12找到这个:

跟进可以看见这个:

得到flag:flag{1999902069a45792d233ac}

[ACTF新生赛2020]easyre

这题有壳,但是upx -d可以解决,所以脱以下子:

进去看见这个:

发现v10和v6应当是连在一起的,给他们make array一下:

之后使用我们在小学二年级就会的知识写个代码:

#include <iostream>

using namespace std;

int main()
{
    int key[99] = {126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 
  116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 
  106, 105, 104, 103, 102, 101, 100,  99,  98,  97, 
   96,  95,  94,  93,  92,  91,  90,  89,  88,  87, 
   86,  85,  84,  83,  82,  81,  80,  79,  78,  77, 
   76,  75,  74,  73,  72,  71,  70,  69,  68,  67, 
   66,  65,  64,  63,  62,  61,  60,  59,  58,  57, 
   56,  55,  54,  53,  52,  51,  50,  49,  48,  47, 
   46,  45,  44,  43,  42,  41,  40,  39,  38,  37, 
   36,  35,  32,  33,  34};
    char ans[99] = "*F'\"N,\"(I?+@";
    int i, j;
    for(i = 0; i <= 11; i++)
    {
          for(j = 0; j <= 94; j++)
          {
    		if(ans[i] == key[j])
    		{
    			cout << char(j + 1);
		}
          }
    }
	return 0;
}

得到flag:flag{U9X_1S_W6@T?}

[ACTF新生赛2020]rome

拖进IDA进行一个array的make和一个名字的改,得到这个东西:

在进行一个代码的写:

#include <iostream>

using namespace std;

int main()
{
	char key[99] = "Qsw3sj_lz4_Ujw@l";
	int i, j, tmp;
	bool f;
	for(i = 0; i <= 15; i++)
	{
		f = true;
		for(j = 65; j <= 122; j++)
		{
			if(j >= 'A' && j <= 'Z')
			{
				tmp = (j - 51) % 26 + 65;
			}
			if(j >= 'a' && j <= 'z')
			{
				tmp = (j - 79) % 26 + 97;
			}
			if(tmp == key[i])
			{
				f = false;
				cout << char(j);
			}
		}
		if(f == true)
		{
			cout << key[i];
		}
	}
	return 0;
}

得到flag:flag{Cae3ar_th4_Gre@t}

[2019红帽杯]easyRE

起始函数很抽象,shift+F12寻找特征字符串,跟进发现:

它做了10次base64加密,经过解密得到:“https://bbs.pediy.com/thread-254172.htm”
好,被骗了。。。
开始往前搜索信息:

把这一坨东西给他异或回去得到:Info:The first four chars are `flag`
怎么说呢,既有用,又没用。。。
不过在跟进off_6CC090中发现了这两个被函数调用过的给定数组:

跟进函数看见:

解读出v4这个东西异或之后首位是f,末位是g,推测整体异或之后是“flag”,反向把v4解出来,再讲for循环异或回去:

#include <iostream>

using namespace std;

int main()
{
	int ans[99] =
	{
	   64,  53,  32,  86,  93,  24,  34,  69,  23,  47, 
	   36, 110,  98,  60,  39,  84,  72, 108,  36, 110, 
	  114,  60,  50,  69,  91
	};
	int i, tmp;
	int key[5];
	char s[5] = "flag";
	for(i = 0; i <= 3; i++)
	{
		key[i] = ans[i] ^ s[i];
	}
	for(i = 0; i <= 24; i++)
	{
		tmp = ans[i] ^ key[i % 4];
		cout << char(tmp);
	}
	return 0;
}

得到flag:flag{Act1ve_Defen5e_Test}
题出的很好,下次不要出了。

[GUET-CTF2019]re

有壳,但是可以upx -d:

点进去通过shift+F12获取关键字,跳转到:

点进sub_4009AE函数,它会让你做32个乘法题,鼓捣鼓捣发现a1[6]不见了,所以爆破一下得到flag:flag{e165421110ba03099a1c039337}

[WUSTCTF2020]level1

拖进IDA发现:

再根据提供的输出文档,写一个简单的代码:

#include <iostream>

using namespace std;

int main()
{
	long long ans[99] = {0,198,232,816,200,1536,300,6144,984,51200,570,92160,1200,565248,756,1474560,800,6291456,1782,65536000};
	int i;
	for(i = 1; i <= 19; i++)
	{
		if((i & 1) == 0)
		{
			cout << char(ans[i] / i);
		}
		else
		{
			cout << char(ans[i] >> i);
		}
	}
	return 0;
}

得到flag:flag{d9-dE6-20c}

[SUCTF2019]SignIn

这是个RSA,我不理解为什么要出这个。。。
flag:flag{Pwn_@_hundred_years}

[MRCTF2020]Transform

打开得到:

写出脚本:

#include <iostream>

using namespace std;

int main()
{
	int ans[99] = {103, 121, 123, 127, 117,  43,  60,  82,  83, 121, 
   87,  94,  93,  66, 123,  45,  42, 102,  66, 126, 
   76,  87, 121,  65, 107, 126, 101,  60,  92,  69, 
  111,  98,  77};
    int key[99] = {9,10,15,23,7,24,12,6,1,16,3,17,32,29,11,30,27,22,4,13,19,20,21,2,25,5,31,8,18,26,28,14};
    int flag[99];
    int i;
    for(i = 0; i <= 32; i++)
    {
    	ans[i] ^= key[i];
    	flag[key[i]] = ans[i];
	}
	for(i = 0; i <= 32; i++)
	{
		cout << char(flag[i]);
	}
	return 0;
}

得到flag:flag{Tr4nsp0sltiON_Clph3r_1s_3z}

[WUSTCTF2020]level2

有壳,但是可以upx -d,解决后进去即可得到flag:flag{Just_upx_-d}

[ACTF新生赛2020]usualCrypt

进去后可以分析出主加密函数在sub_401080

进去后很开心是个base64,直接解密得到乱码,观察发现函数开始和结尾分别有这两个诡异的东西:

一个更改密码表,一个更改结果,给它推回去:

#include <iostream>

using namespace std;

int main()
{
	char key[99] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	char ans[99] = "zMXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9";
	int i, tmp;
	for(i = 6; i < 15; i++)
	{
		tmp = key[i + 10];
		key[i + 10] = key[i];
		key[i] = tmp;
	}
	for(i = 0; i <= 35; i++)
	{
		if(ans[i] >= 'a' && ans[i] <= 'z')
		{
			ans[i] -= 32;
		}
		else
		{
			if(ans[i] >= 'A' && ans[i] <= 'Z')
			{
				ans[i] += 32;
			}
		}
	}
	for(i = 0; i <= 63; i++)
	{
		cout << key[i];
	}
	cout << endl;
	for(i = 0; i <= 35; i++)
	{
		cout << ans[i];
	}
	return 0;
}

得到新的密码表:ABCDEFQRSTUVWXYPGHIJKLMNOZabcdefghijklmnopqrstuvwxyz0123456789+/
旧结果:ZmxhZ3tiGNXlXjHfaDTzN2FfK3LycRTpc2L9
拿着这两个东西解密得到flag:flag{bAse64_h2s_a_Surprise}

[HDCTF2019]Maze

有壳但是可以upx -d:

进去发现有一个花指令,给它nop掉:

正常编译后得到:

在跟进dword_408078和dword_40807C时顺带找出地图:

由起始坐标(7,0)和结束坐标(5,-4)在根据+和F的位置推出地图长这样:
*******+**
*******s**
****ssss**
**sss*****
**s**F****
**ssss****
**********
走一遍得到flag:flag{ssaaasaassdddw}

[MRCTF2020]Xor

进去F5发现IDA会报个错,跟进提示错误的函数先把它反编译出来,在回来反编译主函数就可以了。应该是IDA遇见了一个它不认识的东西,让他先认识一下就行了:

写个代码:

#include <iostream>

using namespace std;

int main()
{
    int ans[99] = {77,  83,  65,  87,  66, 126,  70,  88,  90,  58, 
   74,  58,  96, 116,  81,  74,  34,  78,  64,  32, 
   98, 112, 100, 100, 125,  56, 103};
    int i;
    for(i = 0; i <= 26; i++)
    {
    	ans[i] ^= i;
    	cout << char(ans[i]);
    }
	return 0;
}

得到flag:flag{@_R3@1ly_E2_R3verse!}

标签:逆向,BUUCTF,int,99,flag,key,第一页,include,IDA
From: https://www.cnblogs.com/Clovershrub/p/16907675.html

相关文章

  • 游戏逆向(注入技术)
    用户层下注入技术:-目标:实现一个用户层注入工具-特点:比较简单,有C语言基础即可学习,大多数功能都是直接调用API即可实现-适合人群:游戏逆向入门级同学-测试游戏:DNF,逆水寒,倩......
  • 逆向递归加正向递归,将无规则树 重建成一棵完整的树
    逆向递归加正向递归,将无规则树重建成一棵完整的树背景后台在一个部门树上任意勾选,然后前端需要知道勾选后重新生成的树,没有父级的找上级依次类推。最近递归写的......
  • BUUCTF之[GUET-CTF2019]--RE
    老样子,先查壳,ELF64而且发现Upx壳.Tips:现在只会最基本的upx-d脱壳,虽然现在不会OEP定律法,以后还是要面对的捏丢kali里面进行脱壳即可丢IDA继续分析首先看字符串窗口......
  • BUUCTF之2019红帽杯--easyre
    老样子,先查壳无壳,ELF64位,丢IDA继续分析即可首先看下字符串表,发现有一大串字符,还有很像Base64索引表的字符串来到主要逻辑函数首先发现,v12,v13,v14是一个大数组,不过......
  • 【iOS逆向与安全】frida-trace入门
    前言frida-trace是一个用于动态跟踪函数调用的工具。支持android和ios。安装教程请参考官网。工欲善其事必先利其器。本文将以某App为示范,演示frida-trace的各种方法在iOS......
  • 141. 环形链表 ----- 哈希表、逆向思维、快慢指针
    给你一个链表的头节点head,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪next指针再次到达,则链表中存在环。为了表示给定链表中的环,评测系统内部使用整......
  • BUUCTF-pwn专题
    buuctf栈溢出ripret2text,返回到代码中本来就有的恶意函数拿到附件后,首先进程checksecRELRO:RELRO会有PartialRELRO和FULLRELRO,如果开启FULLRELRO,意味着我们无法......
  • BUUCTF SameMod
    题目原型:1{6266565720726907265997241358331585417095726146341989755538017122981360742813498401533594757088796536341941659691259323065631249,773}2{6266565720......
  • BUUCTF [ACTF新生赛2020]crypto-rsa3
    题目原型:1fromflagimportFLAG2fromCryptodome.Util.numberimport*3importgmpy24importrandom56e=655377p=getPrime(512)8q=int(gmpy......
  • 小程序逆向 换Otoken实现登录
    最近做小程序逆向,拿到微信开发工具打开虽然没有报错,但是登录的时候一直提示登录身份过期。最终找到解决办法,在这分享一下。手机微信登录小程序,抓包找到Otoken参数然后......