nyist 计科选拔赛逆向题目

弱校 题目及题解 大牛请绕道

 

 

 

 

有题目参考了 别人部分思路  题目中已经表明

此次题目 校内选拔所用 并非用到商业上 如有 使用商业行为  与本人无关

若有侵权 还请告知 本人修改或删除

 

昨天出了半天不到的题目 今天 看着学弟做了一天的题目

一天出了两个题目 而且还没有参考了别人的题目代码 并且 出的比较急

所以出现了很多的问题  不过问题不大 最后基本都修复了一下

现在来看一下 题目下面会有打包链接

链接:https://pan.baidu.com/s/1wxKv1863q4LkNz5PArm-kw
提取码:jy6u
复制这段内容后打开百度网盘手机App,操作更方便哦

 

然后说回题目

 复杂函数^=^

先说一下 参考题目

实验吧 reversemeplz

本人 题解

https://blog.csdn.net/qq_41071646/article/details/89056010

这里扣下了 这个题目的映射函数

然后这个题目限制的是 WPSEC{} 里面的字符是小写 要不然就出现了多解的情况

 

源码

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<iostream>
#include<map>
#include<time.h>
#include<queue>
#include "windows.h"
using namespace std;
map<char, char>mapp;
int dword_8049CA4;
void PrintError()
{
	printf("皮皮虾温馨提示您 您的flag不太对哦!!!\n");

	for (int i = 0; i < 8; i++)
	{
		printf("***********   ^=^ ***********\n");
	}
	getchar();
	getchar();
}
char  sub_80484FB(char a1)
{
	++dword_8049CA4;
	++dword_8049CA4;
	return a1;
}
int  sub_8048519(char a1)
{
	unsigned __int8 v1; // al
	signed int v2; // edi
	int v3; // ebx
	signed int v4; // edi
	int v5; // ebx
	signed int v6; // edi
	int v7; // ebx
	signed int v8; // edi
	char v9; // cl
	int v10; // edx
	signed int v11; // edi
	int v12; // edx
	int v13; // edx
	signed int v14; // edi
	signed int v15; // ecx
	int v16; // edx
	signed int v17; // ecx
	int v18; // edx
	signed int v19; // ecx
	int v20; // edx
	signed int v21; // ebx
	int v22; // edx
	signed int v23; // ebx
	int v24; // edx
	signed int v25; // ebx
	int v26; // edx
	signed int v27; // ebx
	int v28; // edx
	signed int v29; // ecx
	int v30; // edx
	signed int v31; // ecx
	int v32; // edx
	signed int v33; // ecx
	signed int v34; // esi
	int v35; // edx
	char v36; // cl
	int v37; // edx
	signed int v38; // esi
	int v39; // edx
	int v40; // edx
	signed int v41; // edi
	int v42; // edx
	signed int v43; // edi
	int v44; // edx
	signed int v45; // ecx
	signed int v46; // esi
	int v47; // edx
	int v48; // esi
	bool v49; // zf
	signed int v50; // eax
	char v52; // [esp+4h] [ebp-10h]

	v1 = sub_80484FB(a1);
	v2 = 19;
	if ((v1 & 0x3F) != 38)
		v2 = 0;
	v3 = v2 | (v1 << 8) | 9 * ((v1 & 0x5F) == 86);
	v4 = 71;
	if ((v1 & 0x77) != 116)
		v4 = 0;
	v5 = v4 | v3;
	v6 = 84;
	if ((v1 & 0x3F) != 39)
		v6 = 0;
	v7 = v6 | v5;
	v8 = 48;
	if ((v1 & 0x4F) != 4)
		v8 = 0;
	v9 = v1 & 0x1F;
	v10 = 3 * ((v1 & 0x57) == 80) | 8 * (v9 == 1) | v7 | v8 | 2 * (v9 == 15) | 2 * ((v1 & 0x5B) == 83);
	v11 = 114;
	v52 = ~v1;
	v12 = 8 * (v9 == 2) | 8 * (v9 == 11) | v10 | 2 * ((v1 & 0x57) == 66) | 8 * ((v1 & 0x2E) == 44);
	if ((v1 & 0x37) != 37)
		v11 = 0;
	v13 = v11 | v12;
	v14 = 16;
	v15 = 0;
	if ((v1 & 0x1C) == 8)
		v15 = 16;
	v16 = ((~v1 & 0x78u) < 1 ? 0x48 : 0) | v15 | v13;
	v17 = 64;
	if ((v1 & 0x1D) != 16)
		v17 = 0;
	v18 = v17 | v16;
	v19 = 0;
	if ((v1 & 0xF) == 11)
		v19 = 16;
	v20 = 4 * ((v1 & 0x55) == 64) | v19 | v18;
	v21 = 72;
	if ((v1 & 0x4B) != 1)
		v21 = 0;
	v22 = v21 | v20;
	v23 = 24;
	if ((v1 & 0x47) != 1)
		v23 = 0;
	v24 = v23 | v22;
	v25 = 96;
	if ((v1 & 0x2B) != 34)
		v25 = 0;
	v26 = ((v52 & 0x55u) < 1 ? 0x48 : 0) | v25 | v24;
	v27 = 0;
	if ((v1 & 0x31) == 16)
		v27 = 16;
	v28 = v27 | v26;
	v29 = 0;
	if ((v1 & 0x55) == 81)
		v29 = 68;
	v30 = v29 | v28;
	v31 = 0;
	if ((v1 & 0xE) == 8)
		v31 = 32;
	v32 = v31 | v30;
	v33 = 97;
	if ((v1 & 0x59) != 72)
		v33 = 0;
	v34 = 81;
	v35 = v33 | v32;
	v36 = v1 & 0x17;
	if ((v1 & 0x17) != 4)
		v34 = 0;
	v37 = v34 | v35;
	v38 = 37;
	if ((v1 & 0x47) != 66)
		v38 = 0;
	v39 = v37 | v38 | 8 * ((v1 & 0x43) == 2);
	if ((v1 & 0x46) != 2)
		v14 = 0;
	v40 = v14 | v39;
	v41 = 80;
	if (v36 != 3)
		v41 = 0;
	v42 = v41 | v40;
	v43 = 70;
	if (v36 != 1)
		v43 = 0;
	v44 = v43 | v42;
	v45 = 40;
	if ((v1 & 0x70) != 64)
		v45 = 0;
	v46 = 0;
	v47 = 4 * ((v1 & 0x41) == 1) | ((v52 & 0xBu) < 1 ? 0x60 : 0) | v45 | v44;
	if ((v1 & 0x48) == 64)
		v46 = 32;
	v48 = v47 | v46;
	v49 = (v1 & 0x21) == 1;
	v50 = 0;
	if (v49)
		v50 = 68;
	return v48 | v50;
}

//bargjbgursyntlb
int main()
{

	char ss[] = "cvcvkvnpnyylbhtbbq";
	char s[100];
	char t;
	scanf("%s", s);
	if (s[0] != 'W'||s[1] != 'P'||s[2] != 'S'||s[3] != 'E'||s[4] != 'C'||s[5] != '{'||s[strlen(s) - 1] != '}')
	{
		PrintError();
		return 0;
		
	}
	if (strlen(s)<8)
	{
		PrintError();
		return 0;
	}
	for (int i = 6; i < strlen(s) - 1;i++)
	{
		t = sub_8048519(s[i]);
		if(t!=ss[i-6])
		{
			//printf("%d %c %c\n", i, sub_8048519(s[i]),ss[i-6]);
			PrintError();
			return 0;
		}

	}
	printf("good!you get flag!!!\n");
	getchar();
	getchar();
	return 0;
}

然后 题解的话

#include <iostream>
using namespace std;


char sub_4438B0(char a1)
{
	unsigned __int8 v1; // al
	signed int v3; // [esp+14h] [ebp-32Ch]
	signed int v4; // [esp+18h] [ebp-328h]
	signed int v5; // [esp+18h] [ebp-328h]
	char v6; // [esp+E3h] [ebp-25Dh]
	signed int v7; // [esp+ECh] [ebp-254h]
	signed int v8; // [esp+11Ch] [ebp-224h]
	signed int v9; // [esp+128h] [ebp-218h]
	signed int v10; // [esp+140h] [ebp-200h]
	signed int v11; // [esp+158h] [ebp-1E8h]
	signed int v12; // [esp+17Ch] [ebp-1C4h]
	char v13; // [esp+197h] [ebp-1A9h]
	signed int v14; // [esp+1ACh] [ebp-194h]
	signed int v15; // [esp+1B8h] [ebp-188h]
	signed int v16; // [esp+1D0h] [ebp-170h]
	signed int v17; // [esp+1E8h] [ebp-158h]
	signed int v18; // [esp+200h] [ebp-140h]
	signed int v19; // [esp+218h] [ebp-128h]
	signed int v20; // [esp+230h] [ebp-110h]
	signed int v21; // [esp+248h] [ebp-F8h]
	signed int v22; // [esp+260h] [ebp-E0h]
	signed int v23; // [esp+278h] [ebp-C8h]
	int v24; // [esp+284h] [ebp-BCh]
	signed int v25; // [esp+290h] [ebp-B0h]
	signed int v26; // [esp+29Ch] [ebp-A4h]
	signed int v27; // [esp+2C0h] [ebp-80h]
	signed int v28; // [esp+2E4h] [ebp-5Ch]
	signed int v29; // [esp+2FCh] [ebp-44h]
	signed int v30; // [esp+314h] [ebp-2Ch]
	signed int v31; // [esp+32Ch] [ebp-14h]

	v1 = a1;
	v31 = 19;
	if ((v1 & 0x3F) != 38)
		v31 = 0;
	v30 = 71;
	if ((v1 & 0x77) != 116)
		v30 = 0;
	v29 = 84;
	if ((v1 & 0x3F) != 39)
		v29 = 0;
	v28 = 48;
	if ((v1 & 0x4F) != 4)
		v28 = 0;
	v27 = 114;
	v6 = ~v1;
	if ((v1 & 0x37) != 37)
		v27 = 0;
	v26 = 16;
	v25 = 0;
	if ((v1 & 0x1C) == 8)
		v25 = 16;
	if ((~v1 & 0x78u) >= 1)
		v4 = 0;
	else
		v4 = 72;
	v24 = 8 * ((v1 & 0x2E) == 44) | 2 * ((v1 & 0x57) == 66) | 2 * ((v1 & 0x5B) == 83) | 2 * ((v1 & 0x1F) == 15) | v28 | 9 * ((v1 & 0x5F) == 86) | v31 | (v1 << 8) | v30 | v29 | 8 * ((v1 & 0x1F) == 1) | 3 * ((v1 & 0x57) == 80) | 8 * ((v1 & 0x1F) == 11) | 8 * ((v1 & 0x1F) == 2) | v27 | v25 | v4;
	v23 = 64;
	if ((v1 & 0x1D) != 16)
		v23 = 0;
	v22 = 0;
	if ((v1 & 0xF) == 11)
		v22 = 16;
	v21 = 72;
	if ((v1 & 0x4B) != 1)
		v21 = 0;
	v20 = 24;
	if ((v1 & 0x47) != 1)
		v20 = 0;
	v19 = 96;
	if ((v1 & 0x2B) != 34)
		v19 = 0;
	if ((v6 & 0x55u) >= 1)
		v5 = 0;
	else
		v5 = 72;
	v18 = 0;
	if ((v1 & 0x31) == 16)
		v18 = 16;
	v17 = 0;
	if ((v1 & 0x55) == 81)
		v17 = 68;
	v16 = 0;
	if ((v1 & 0xE) == 8)
		v16 = 32;
	v15 = 97;
	if ((v1 & 0x59) != 72)
		v15 = 0;
	v14 = 81;
	v13 = v1 & 0x17;
	if ((v1 & 0x17) != 4)
		v14 = 0;
	v12 = 37;
	if ((v1 & 0x47) != 66)
		v12 = 0;
	if ((v1 & 0x46) != 2)
		v26 = 0;
	v11 = 80;
	if (v13 != 3)
		v11 = 0;
	v10 = 70;
	if (v13 != 1)
		v10 = 0;
	v9 = 40;
	if ((v1 & 0x70) != 64)
		v9 = 0;
	v8 = 0;
	if ((v6 & 0xBu) >= 1)
		v3 = 0;
	else
		v3 = 96;
	if ((v1 & 0x48) == 64)
		v8 = 32;
	v7 = 0;
	if ((v1 & 0x21) == 1)
		v7 = 68;
	return v7 | v8 | 8 * ((v1 & 0x43) == 2) | v12 | v24 | v23 | v22 | 4 * ((v1 & 0x55) == 64) | v21 | v20 | v19 | v5 | v18 | v17 | v16 | v15 | v14 | v26 | v11 | v10 | v9 | v3 | 4 * ((v1 & 0x41) == 1);
}

int main()
{

	string key = string({0x63,0x76,0x63,0x76,0x6b,0x76,0x6e,0x70,0x6e,0x79,0x79,0x6c,0x62,0x68,0x74,0x62,0x62,0x71});
	cout << key << endl;
	string flag = "WPSEC{" + key + "}";
	for (int i = 0; i < key.length(); i++) {
		for (char j = 'a'; j < 'z'+1; j++) {
			if (sub_4438B0(j) == key[i]) {
				flag[6 + i] = (char)j;
				cout << "found!" << endl;
				break;
			}
		}
		cout << endl;
	}
	cout << flag << endl;
	return 0;
}

咳咳咳

这个题目 是带上壳的 是一个学弟写的 我直接让学弟把这个题 出了

脱壳的话 找到OEP 就可以了 学弟写这个壳 用 esp是不行的   单步可以搞定

然后跟进

然后 dump可能会有卡顿  等一会就好了 然后

直接点开不太行 还需要修复一下 IAT表

成功 运行了程序

然后  找到 按钮函数  ida 反编译一下

然后这里是 源码 验证部分

void CMFCDlg::OnBnClickedOk()
{
	char flag[] = { 95, 88, 91, 77, 75, 116, 75, 63, 107, 79, 119, 100, 113, 112, 62, 100, 113, 105, 63, 70, 58, 80, 112, 80, 79, 79, 79, 79, 79, 71, 71, 71, 71, 92, 92, 92, 92, 80, 62, 113, 114,0 };
	char ok[] = { 106, 110,0 };
	bool isright = true;
	CString in;
	GetDlgItem(IDC_EDIT1)->GetWindowText(in);
	USES_CONVERSION;
	char* got = T2A(in);
	for (int i = 0; i < strlen(got); i++)
	{
		if (got[i] >= 'a' && got[i] <= 'z')
			got[i] ^= 0x5;
		else if (got[i] >= 'A' && got[i] <= 'Z')
			got[i] ^= 0x8;
		else got[i] ^= 0xF;
	}
	if (strlen(got) == strlen(flag))
	{
		for (int i = 0; i < strlen(got); i++)
			if (got[i] != flag[i])
				isright = false;
		if (isright == true)
		{
			ok[0] ^= 0x5; ok[1] ^= 0x5;
			MessageBoxA(0, (LPCSTR) ok, (LPCSTR) ok, 0);
		}
	}
}

IDA里面看的也比较清楚

给出了源码 这里就不写得出flag的脚本了 感觉听简单的

 

迷宫题目算是原创的了  因为懒得写题解 就把一个题目的图给用了

这个是我写的那个题目的题解

https://blog.csdn.net/qq_41071646/article/details/97805225

这个是原题代码

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<iostream>
#include<map>
#include<time.h>
#include<queue>
#include "windows.h"
using namespace std;
char slist[14][17] =
{ "****************",
"o..............*",
"**************.*",
"************...*",
"***********..***",
"**********..****",
"*********..*****",
"********..******",
"*******..*******",
"******..********",
"*****..*********",
"****..**********",
"****7***********",
"****************", };
bool pan(int x,int y)
{
	if (x < 0 || x >= 14 || y < 0 || y >= 17 || slist[x][y]=='*')
		return 0;
	return 1;

}
void pipixia()
{
	printf("flag 长度为 42");
}
void PrintError()
{
	printf("皮皮虾温馨提示您 您的flag不太对哦!!!\n");

	for (int i = 0; i < 8;i++)
	{
		printf("***********   ^=^ ***********\n");
	}
	getchar();
	getchar();
}
int main()
{
	int list = 100;
	int nice = 1204;
	char s[100];
	scanf("%s", s);
	if (s[0]!='W'||s[1]!='P'||s[2]!='S'||s[3]!='E'||s[4]!='C'||s[5]!='{'||s[strlen(s)-1]!='}')
	{
		PrintError();
		return 0;
	}
	if (strlen(s)<6)
	{
		PrintError();
		return 0;
	}
	for (int i = 6; i<int(strlen(s)-1);i++)
	{

		switch (s[i])
		{
		case 'a':
			list = list - 1;
			break;
		case 'd':
				list = list + 1;
				break;
		case 'w':
			list = (list / 100 - 1) * 100 + list % 100;
			break;
		case 's':
			list = (list / 100 + 1) * 100 + list % 100;
			break;	
			
		}
		
		if(!pan(list/100,list%100))
		{
			PrintError();
			return 0;
		}
		
	}
	if (list == nice)
	{
		printf("good!you get flag!!!\n");
	}
	else
	{
		printf("%d %d", list, nice);
		printf("where are you go???");
	}
	getchar();
	getchar();
	return 0;
}

那么 搜索就可以解决

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<iostream>
#include<map>
#include<time.h>
#include<queue>
#include "windows.h"
using namespace std;
char s[14][17] =
{ "****************",
"o..............*",
"**************.*",
"************...*",
"***********..***",
"**********..****",
"*********..*****",
"********..******",
"*******..*******",
"******..********",
"*****..*********",
"****..**********",
"****7***********",
"****************", };
int hh[5] = { 1, 0, -1, 0 };//y
int kk[5] = { 0, 1, 0, -1 };//x
char w[5] = { 'd', 's', 'a', 'w' };
//a 左 d右 s下 w上
bool vis[20][20];
struct code{
	int x, y;
	queue<char>l;
}as, ad;
bool pd(int i, int j)
{
	if (i >= 0 && i<14 && j >= 0 && j<16 && !vis[i][j] && s[i][j] != '*')
		return 1;
	return 0;
}

void slove()
{
	memset(vis, 0, sizeof(vis));
	queue<code>qq;
	as.x = 1, as.y = 0;
	while (!as.l.empty())
		as.l.pop();
	qq.push(as);
	while (!qq.empty())
	{
		ad = qq.front();
		qq.pop();
		//printf("%d %d\n",ad.x,ad.y);
		if (s[ad.x][ad.y] == '7')
		{
			while (!ad.l.empty())
			{
				printf("%c", ad.l.front());
				ad.l.pop();
			}
			return;
			// printf("1\n");
			// printf("\n");
		}
		for (int i = 0; i<4; i++)
		{
			as = ad;
			as.x = ad.x + kk[i];
			as.y = ad.y + hh[i];
			if (pd(as.x, as.y))
			{
				//printf("%d %d %c\n",as.x,as.y,w[i]);
				as.l.push(w[i]);
				qq.push(as);
				vis[as.x][as.y] = 1;
			}
		}
	}

}
int main()
{
	slove();
	getchar();
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值