欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]CTF第二题的求解思路

[原创]CTF第二题的求解思路

工具IDA,OD,VC++
不知道如果最后扫描不出来结果可不可以通过
求解主要是获取到两个变量v1和v2,同时满足以下等式

5 * (v1 - v0) + v1 == -1890567614 && 13 * (v1 - v0) + v0 == -279954878

17 * (v1 - v0) + v1 == -207009661 && 7 * (v1 - v0) + v0 == 866732163

可以看出
v1 mod 5 = -1890567614 mod 5
v1 mod 17 = -207009661 mod 17
v0 mod 13 = -279954878 mod 13
v0 mod 7 = 866732163 mod 7
根据剩余定理可以推测出v1和v0的可能的一系列值,然后再暴力尝试可能的值,最后确定出v1和v0的值
破解代码如下:

#include "stdafx.h"

#include "stdio.h"

//中国剩余定理  

struct node {

	int divisor;            //表示除数  

	int  remainder;     //表示余数  

}T[1000];

//求最大公约数  

int gcd(int n, int m)

{

	return m ? gcd(m, n%m) : n;

}

int v1[0x7ffffff] = { 0 };

int v0[0x7ffffff] = { 0 };

int getV(int b0, int b1, int l0, int l1, int* v) {

	//MAX_NUM表示的是所求的解的范围的最大值,MIN_NUM表示所求的解的范围的最小值,  

	//n表示的是同于方程的个数,m表示的是三个除数的乘积,gcd_max表示的是两个数的最大公约数,因为三个除数是互素的  

	//所以gcd_max=1;  

	int i, j, n, t = 0, m = 1, sum = 0, gcd_max = 0, MAX_NUM, MIN_NUM;

	//printf("请输入有几个方程:\n");   //如上题韩信点兵。输入3  

	//scanf_s("%d", &n);

	printf("请输入每组数据(  余数 除数):\n"); // 3 2 5 4 7 6  

	n = 2;

	T[0].remainder = b0 % l0;

	T[0].divisor = l0;

	T[1].remainder = b1 % l1;

	T[1].divisor = l1;

	//printf("请输入所求值的值域:min max\n");

	//scanf_s("%x%x", &MIN_NUM, &MAX_NUM);

	//求出三个除数的乘积m  

	for (i = 0; i < n; i++) {

		gcd_max = gcd(T[i].divisor, gcd_max);

		m = m * T[i].divisor;

	}

	gcd_max *= m;

	//求mI  

	for (i = 0; i < n; i++)

	{

		t = 0; m = 1;

		for (j = 0; j < n; j++)

		{

			if (j != i)

			{

				t = gcd(T[j].divisor, t);

				m = m * T[j].divisor;

			}

		}

		t = m * t;

		m = t;

		while (m % T[i].divisor != 1)

			m += t;

		sum += m * T[i].remainder;

	}

	printf("最小的值为:\n");

	printf("%d\n", sum % gcd_max);

	printf("在所求的值域内值:\n");

	printf("%x\n", sum);

	int count = 0;

	while (sum < 0x7e7e7e7e) {

		if (sum >= 0x20202020) {

			//&& (sum & 0xff000000) >= 0x20000000 && (sum & 0xff000000) <= 0x7e000000

			//&& (sum & 0x00ff0000) >= 0x00200000 && (sum & 0x00ff0000) <= 0x007e0000

			//&& (sum & 0x0000ff00) >= 0x00002000 && (sum & 0x0000ff00) <= 0x00007e00

			//&& (sum & 0x000000ff) >= 0x00000020 && (sum & 0x000000ff) <= 0x0000007e) {

			//printf("0x%x   \n", sum);

			v[count] = sum;

			count += 1;

		}

		sum += gcd_max;

	}

	printf("%x\n", sum);

	printf("%d\n", count);

	return count;

}

int main()

{

	int b0 = 0x8F503a42;

	int b1 = 0xEF503a42;

	int b2 = 0xF3A94883;

	int b3 = 0x33A94883;

	printf("%i<->5\n", b0 % 5);

	printf("%i<->17\n", b2 % 17);

	printf("%i<->13\n", b1 % 13);

	printf("%i<->7\n", b3 % 7);

	int len1 = getV(b0, b2, 5, 17, v1);

	int len0 = getV(b1, b3, 13, 7, v0);

	for (int i = 0; i < len1; ++i) {

		for (int j = 0; j < len0; ++j) {

			if ((5 * (v1[i] - v0[j]) + v1[i]) == b0

				&& (13 * (v1[i] - v0[j]) + v0[j]) == b1

				&& (17 * (v1[i] - v0[j]) + v1[i]) == b2

				&& (7 * (v1[i] - v0[j]) + v0[j]) == b3) {

				printf("*********\n");

				printf("v1=0x%x\n", v1[i]);

				printf("v0=0x%x\n", v0[j]);

			}

		}

	}

	printf("No Solution!\n");

	return 0;

}

#include "stdafx.h"

#include "stdio.h"

//中国剩余定理  

struct node {

	int divisor;            //表示除数  

	int  remainder;     //表示余数  

}T[1000];

//求最大公约数  

int gcd(int n, int m)

{

	return m ? gcd(m, n%m) : n;

}

int v1[0x7ffffff] = { 0 };

int v0[0x7ffffff] = { 0 };

int getV(int b0, int b1, int l0, int l1, int* v) {

	//MAX_NUM表示的是所求的解的范围的最大值,MIN_NUM表示所求的解的范围的最小值,  

	//n表示的是同于方程的个数,m表示的是三个除数的乘积,gcd_max表示的是两个数的最大公约数,因为三个除数是互素的  

	//所以gcd_max=1;  

	int i, j, n, t = 0, m = 1, sum = 0, gcd_max = 0, MAX_NUM, MIN_NUM;

	//printf("请输入有几个方程:\n");   //如上题韩信点兵。输入3  

	//scanf_s("%d", &n);

	printf("请输入每组数据(  余数 除数):\n"); // 3 2 5 4 7 6  

	n = 2;

	T[0].remainder = b0 % l0;

	T[0].divisor = l0;

	T[1].remainder = b1 % l1;

	T[1].divisor = l1;

	//printf("请输入所求值的值域:min max\n");

	//scanf_s("%x%x", &MIN_NUM, &MAX_NUM);

	//求出三个除数的乘积m  

	for (i = 0; i < n; i++) {

		gcd_max = gcd(T[i].divisor, gcd_max);

		m = m * T[i].divisor;

	}

	gcd_max *= m;

	//求mI  

	for (i = 0; i < n; i++)

	{

		t = 0; m = 1;

		for (j = 0; j < n; j++)

		{

			if (j != i)

			{

				t = gcd(T[j].divisor, t);

				m = m * T[j].divisor;

			}

		}

		t = m * t;

		m = t;

		while (m % T[i].divisor != 1)

			m += t;

		sum += m * T[i].remainder;

	}

	printf("最小的值为:\n");

	printf("%d\n", sum % gcd_max);

	printf("在所求的值域内值:\n");

	printf("%x\n", sum);

	int count = 0;

	while (sum < 0x7e7e7e7e) {

		if (sum >= 0x20202020) {

			//&& (sum & 0xff000000) >= 0x20000000 && (sum & 0xff000000) <= 0x7e000000

			//&& (sum & 0x00ff0000) >= 0x00200000 && (sum & 0x00ff0000) <= 0x007e0000

			//&& (sum & 0x0000ff00) >= 0x00002000 && (sum & 0x0000ff00) <= 0x00007e00

			//&& (sum & 0x000000ff) >= 0x00000020 && (sum & 0x000000ff) <= 0x0000007e) {

			//printf("0x%x   \n", sum);

			v[count] = sum;

			count += 1;

		}

		sum += gcd_max;

	}

	printf("%x\n", sum);

	printf("%d\n", count);

	return count;

}

int main()

{

	int b0 = 0x8F503a42;

	int b1 = 0xEF503a42;

	int b2 = 0xF3A94883;

	int b3 = 0x33A94883;

	printf("%i<->5\n", b0 % 5);

	printf("%i<->17\n", b2 % 17);

	printf("%i<->13\n", b1 % 13);

	printf("%i<->7\n", b3 % 7);

	int len1 = getV(b0, b2, 5, 17, v1);

	int len0 = getV(b1, b3, 13, 7, v0);

	for (int i = 0; i < len1; ++i) {

		for (int j = 0; j < len0; ++j) {

			if ((5 * (v1[i] - v0[j]) + v1[i]) == b0

				&& (13 * (v1[i] - v0[j]) + v0[j]) == b1

				&& (17 * (v1[i] - v0[j]) + v1[i]) == b2

				&& (7 * (v1[i] - v0[j]) + v0[j]) == b3) {

				printf("*********\n");

				printf("v1=0x%x\n", v1[i]);

				printf("v0=0x%x\n", v0[j]);

			}

		}

	}

	printf("No Solution!\n");

	return 0;

}

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功