【C语言】SCU安全项目1-FindKeys

目录

前言

 命令行参数

16进制转字符串

extract_message1

process_keys12

extract_message2

main

process_keys34


前言

因为这个学期基本都在搞CTF的web方向,C语言不免荒废。所幸还会一点指针相关的知识,故第一个安全项目做的挺顺利的,也把思维切换切换,接触点新东西。

贴出源码

#include <stdio.h>
#include <stdlib.h>

int prologue[] = {
	0x5920453A, 0x54756F0A, 0x6F6F470A, 0x21643A6F,
	0x6E617920, 0x680A6474, 0x6F697661, 0x20646E69,
	0x63636363, 0x63636363, 0x72464663, 0x6F6D6F72,
	0x63636363, 0x63636363, 0x72464663, 0x6F6D6F72,
	0x2C336573, 0x7420346E, 0x20216F74, 0x726F5966,
	0x7565636F, 0x20206120, 0x6C616763, 0x74206C6F,
	0x20206F74, 0x74786565, 0x65617276, 0x32727463,
	0x594E2020, 0x206F776F, 0x79727574, 0x4563200A
};

int data[] = {
	0x63636363, 0x63636363, 0x72464663, 0x6F6D6F72,
		0x466D203A, 0x65693A72, 0x43646E20, 0x6F54540A,
		0x5920453A, 0x54756F0A, 0x6F6F470A, 0x21643A6F,
		0x594E2020, 0x206F776F, 0x79727574, 0x4563200A,
		0x6F786F68, 0x6E696373, 0x6C206765, 0x796C656B,
		0x2C336573, 0x7420346E, 0x20216F74, 0x726F5966,
		0x7565636F, 0x20206120, 0x6C616763, 0x74206C6F,
		0x20206F74, 0x74786565, 0x65617276, 0x32727463,
		0x6E617920, 0x680A6474, 0x6F697661, 0x20646E69,
		0x21687467, 0x63002065, 0x6C6C7861, 0x78742078,
		0x6578206F, 0x72747878, 0x78636178, 0x00783174
};

int epilogue[] = {
	0x594E2020, 0x206F776F, 0x79727574, 0x4563200A,
	0x6E617920, 0x680A6474, 0x6F697661, 0x20646E69,
	0x7565636F, 0x20206120, 0x6C616763, 0x74206C6F,
	0x2C336573, 0x7420346E, 0x20216F74, 0x726F5966,
	0x20206F74, 0x74786565, 0x65617276, 0x32727463
};

char message[100];

void usage_and_exit(char* program_name) {
	fprintf(stderr, "USAGE: %s key1 key2 key3 key4\n", program_name);
	exit(1);
}

void process_keys12(int* key1, int* key2) {

	*((int*)(key1 + *key1)) = *key2;
}

void process_keys34(int* key3, int* key4) {

	*(((int*)&key3) + *key3) += *key4;
}

char* extract_message1(int start, int stride) {
	int i, j, k;
	int done = 0;

	for (i = 0, j = start + 1; !done; j++) {				
		for (k = 1; k < stride; k++, j++, i++) {

			if (*(((char*)data) + j) == '\0') {
				done = 1;
				break;
			}

			message[i] = *(((char*)data) + j);
		}
	}
	message[i] = '\0';
	return message;
}


char* extract_message2(int start, int stride) {     
	int i, j;

	for (i = 0, j = start;
		*(((char*)data) + j) != '\0';
		i++, j += stride)
	{
		message[i] = *(((char*)data) + j);
	}
	message[i] = '\0';
	return message;
}

int main(int argc, char* argv[])
{
	int dummy = 1;
	int start, stride;
	int key1, key2, key3, key4;
	char* msg1, * msg2;

	key3 = key4 = 0;
	if (argc < 3) {
		usage_and_exit(argv[0]);
	}
	key1 = strtol(argv[1], NULL, 0);
	key2 = strtol(argv[2], NULL, 0);
	if (argc > 3) key3 = strtol(argv[3], NULL, 0);
	if (argc > 4) key4 = strtol(argv[4], NULL, 0);

	process_keys12(&key1, &key2);

	start = (int)(*(((char*)&dummy)));      
	stride = (int)(*(((char*)&dummy) + 1));	     

	if (key3 != 0 && key4 != 0) {
		process_keys34(&key3, &key4);
	}

	msg1 = extract_message1(start, stride);

	if (*msg1 == '\0') {
		process_keys34(&key3, &key4);
		msg2 = extract_message2(start, stride);
		printf("%s\n", msg2);
	}
	else {
		printf("%s\n", msg1);
	}

	return 0;
}

 命令行参数

在C语言程序中,主函数main()可以有两个参数,用于接收命令行参数。带有参数的函数main()习惯上书写为:

(颇有pearcmd的感觉哈哈哈)

int main(int argc,char *argv[])
{
...
}

argc和argv是函数main()的形参(argc和argv分别是argument count和argument vector的缩写)。用命令行的方式运行程序时,函数main()被调用,与命令行有关的信息作为实参传递给两个形参。

第一个参数argc接收命令行参数(包括命令)的个数;第二个参数argv接受以字符串常量形式存放的命令行参数(包括命令本身也作为一个参数)。字符指针数组argv[]表示各个命令行参数(包括命令),其中argv[0]指向命令,argv[1]指向第1个命令行参数,argv[2]指向第2个命令行参数......argv[argc-1]指向最后一个命令行参数。

审一下源码的这部分

其实就是让我们最少传2个参数(第0个参数为程序名),否则就会exit

16进制转字符串

这里显然只有data数组有用,只需要转换data数组即可

如果直接用16进制转字符串的网站,会发现转换结果并不正确

于是跟着代码逻辑自己写一版16进制逐字节解码程序

#include <stdio.h>

	int data[] = {
	0x63636363, 0x63636363, 0x72464663, 0x6F6D6F72,
		0x466D203A, 0x65693A72, 0x43646E20, 0x6F54540A,
		0x5920453A, 0x54756F0A, 0x6F6F470A, 0x21643A6F,
		0x594E2020, 0x206F776F, 0x79727574, 0x4563200A,
		0x6F786F68, 0x6E696373, 0x6C206765, 0x796C656B,
		0x2C336573, 0x7420346E, 0x20216F74, 0x726F5966,
		0x7565636F, 0x20206120, 0x6C616763, 0x74206C6F,
		0x20206F74, 0x74786565, 0x65617276, 0x32727463,
		0x6E617920, 0x680A6474, 0x6F697661, 0x20646E69,
		0x21687467, 0x63002065, 0x6C6C7861, 0x78742078,
		0x6578206F, 0x72747878, 0x78636178, 0x00783174
	};
	void decode1(int* data)
	{
		for (int i = 0; ; i++) {
			char c = *(((char*)data) + i);
			putchar(c);
			if (c == '\0') break;
		}
	}
	int main()
	{
		decode1(data);
		return 0;
	}

运行结果

两者的差异是什么原因呢?

因为Intel处理器是小端,所以数组里每个int的低位存储在内存的低地址处,即先被转化

例如

int 0x5A33723479(Z3r4y)

在内存中:

79 34 72 33 5A(y4r3Z)

所以我们把data的数据先预处理一下再放入16进制转字符串在线网站即可(虽然没有必要)

接下来看一些关键代码

extract_message1

传入一个start和stride,将data数组转换成字符串

这个函数的功能是,从 data 数组的首地址偏移 start + 1 地址开始,每转换 stride -1 个字符后,就跳过一个字符不转换,重复执行这样的操作直到转换到最后一个字符

已知明文最开始为:From: ,可利用其来倒推出start和stride

这里显然是从第10个字符开始(从0开始计数),每次转换两个字符,故start=9,stride=3

 再发现start和stride是由dummy得来的

将dummy最低的字节赋值给start(要等于9),将dummy第二低的字节赋值给stride(要等于3)

即dummy为0x????0309

记录一下低2位转10进制是777

process_keys12

 访问以 key1 变量的地址为初始地址,偏移 *key1 的值×sizeof(int) 即4字节的地址,赋成*key2的值。

这里就可以操纵key1地址将其偏移到dummy的地址,再操纵*key2来控制dummy的值

调试看key1和dummy的地址

(左为key1,右为dummy)

计算地址差值

24➗4=9 ,所以只要令*key1=9即可偏移到dummy的地址

再令*key2=777,使得dummy为0x00000309,成功使得start为9,stride为3

回显正确

提示我们要选择key3key4来调用extract2并且避免调用extract1

extract_message2

其实和extract_message1大同小异

从 data 数组的首地址偏移 start 地址开始,每读入一个字符,就跳过stride-1个字符,直到转换到最后一个字符

可见start=9,stride=3 (刚好就是msg1对应的数据,故key1,key2传的值不用改)

main

 通过代码审计,发现只要让extract_message1返回一个空字符串就可以打印出msg2

我们接着看,怎么操纵msg1='\0'

extract1 最初会访问第10个字符(从0开始计数),而第10个字符恰好会在 extract2 (从第9个字符开始,每隔2个取一个)中被忽略不会影响答案。
所以我们可以直接尝试改变 data 数组,使其表示的第10个字符为 \0 ,即将data[2]=0x72464663转变成 0x72004663 。
可以借助 process_keys34 来操纵data[2]

process_keys34

 这个函数就是把指向key3指针的地址偏移*key3的值×sizeof(int)即4个字节的地址,将其解引用,自增一个*key4的值

那么我们就可以将指向key3指针的地址偏移到data[2]上,然后利用*key4改变data[2]的值,这里72004663-72464663=-4587520,key4传入-4587520即可

调试观察&key3和data[2]的地址

 2597600/4=649400

所以key3传入649400

综上,key1,key2,key3,key4分别传入9 777 649400 -4587520

运行回显正确

实验1还是比较友好的,做的时候没有太坐牢,对于一个C语言小白这种难度刚刚好QWQ

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/244019.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

模型放置到3D场景中后模型位置与鼠标选中的位置不一致怎么办?

在线工具推荐&#xff1a;3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 1、问题 从事3D建模相关工作的朋友们在工作中经常会遇到以下几种问题&#…

速卖通商品API接口的使用指南与示例

一、引言 速卖通&#xff08;AliExpress&#xff09;是阿里巴巴旗下的全球性跨境电商平台&#xff0c;为全球消费者和商家提供了一个便捷的在线交易平台。为了方便商家和开发者获取速卖通商品详情&#xff0c;速卖通提供了商品API接口。本文将详细介绍如何通过速卖通商品API接…

防火墙无非就这8种类型,小白完全不用怕!

你们好&#xff0c;我的网工朋友。 当我们谈到网络开放性带来的安全挑战时&#xff0c;都会想起黑客、病毒、恶意软件等等。 而正是因为这些威胁&#xff0c;让网络安全变成了网络世界里的重要议题&#xff0c;如果说起怎么保护网络安全&#xff0c;基本上我们都会第一时间想…

商城免费搭建之java鸿鹄云商 java电子商务商城 Spring Cloud+Spring Boot+mybatis+MQ+VR全景+b2b2c

鸿鹄云商 SAAS云产品概述 1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、My…

软信天成:企业数据目录加速数据资产管理智能化升级

随着数字时代的来临&#xff0c;数据的作用日益凸显&#xff0c;数字化能有效提高企业的运作效率。据调查统计, 数据领先型企业的指标比数据感知型企业领先50%左右。各界对数据治理的关注度逐年攀升&#xff0c;并且呈现经济越发达&#xff0c;越重视数据治理的态势。越来越多的…

Django、Echarts异步请求、动态更新

前端页面 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>echarts示例</title> <script src"jquery.min.js"></script><script type "text/javascript" src "echarts.m…

【IDEA】关于快捷键行注释时会从行首开始注释

前言 每次在使用IDEA写代码时&#xff0c;用快捷键进行行注释的时候&#xff0c;//会处于行首位置 但是我们想要的是这种注释效果 修改 IDEA中打开settings 找到Editor - Code Style- Java - 找到Code Genneration&#xff0c;取消勾选Line comment at first column&#x…

爱名网被评为“最佳安全保障注册服务机构”

12月12日&#xff0c;由中国互联网络信息中心主办&#xff0c;中国科学院计算机网络信息中心、中国工业互联网研究院、中国互联网协会联合主办&#xff0c;人民邮电报社承办的第四届中国互联网基础资源大会&#xff08;CNIRC&#xff09;在北京举办。 在本届大会上&#xff0c…

配置策略路由(基于IP地址)示例

策略路由简介 定义 策略路由PBR&#xff08;Policy-Based Routing&#xff09;是一种依据用户制定的策略进行路由选择的机制&#xff0c;其优先级高于直连路由、静态路由和通过动态路由协议生成的路由。设备配置策略路由后&#xff0c;若接收的报文&#xff08;包括二层报文&…

数字电子技术期末知识点总结

文章目录 时序逻辑电路时序电路的分析同步时序电路的分析例子1&#xff08;有输入输出&#xff09;例子2 &#xff08;只有输出&#xff09;例子3&#xff08;没有输入、输出&#xff09; 异步时序电路的分析例子1 小结 时序电路的设计同步时序电路的设计串行数据检测器JK 触发…

004 Windows NTFS文件夹权限

一、NTFS文件权限&#xff1a; NTFS&#xff08;New Technology File System&#xff09;是Windows NT内核的系列操作系统支持的、一个特别为网络和磁盘配额、文件加密等管理安全特性设计的磁盘格式&#xff0c;提供长文件名、数据保护和恢复&#xff0c;能通过目录和文件许可…

数据结构和算法-图的基本操作以图的广度优先遍历和深度优先遍历

文章目录 图的基本操作总览找边列出与某顶点相连的边插入顶点删除顶点增加边顶点的第一个邻接点顶点的下一个邻接点设置或者获取某条边的权值总览 图的广度优先遍历总览树的广度优先遍历图的广度优先遍历树vs图图广度优先遍历的代码实现广度优先遍历序列遍历序列的可变性算法存…

如何避免重要文件夹被盗?多种文件夹防盗方法介绍

当我们将重要数据存放在文件夹中时&#xff0c;一定要保护文件夹的安全&#xff0c;避免文件夹被盗。那么&#xff0c;我们该如何避免重要文件夹被盗呢&#xff1f;下面我们就来了解一下。 EFS功能 EFS是Windows提供的数据加密功能&#xff0c;可以加密NTFS卷上的文件和文件夹…

强大的TFTP工具:Transfer免激活最新版

Transfer for Mac功能介绍 从头开始编写的Transfer可以完全控制您的文件传输&#xff0c;同时可以与现有的TFTP客户端完美兼容。Transfer附带对常见TFTP协议扩展和选项的支持&#xff0c;包括&#xff1a; RFC 2347-TFTP选项扩展 RFC 2348-TFTP块大小选项 RFC 2349-TFTP超时…

Paper Reading: (ACRST) 基于自适应类再平衡自训练的半监督目标检测

目录 简介工作重点方法CropBankFBRAFFRTwo-stage Pseudo-label Filtering 实验与SOTA比较消融实验 简介 题目&#xff1a;《Semi-Supervised Object Detection with Adaptive Class-Rebalancing Self-Training》&#xff0c;AAAI’22&#xff0c; 基于自适应类再平衡自训练的半…

快递鸟「物流导盲犬」助力鞋服头部企业客户全链路物流数字化升级

数字化时代&#xff0c;企业全域经营已成为数字商业新浪潮&#xff0c;多店铺多平台多仓库同步发货成为经营常态&#xff0c;消费者对物流服务体验的要求越来越高&#xff0c;企业对物流精细化管理的需求也越来越强烈。快递鸟基于对物流数字化领域的深耕和对行业及客户需求的深…

电流模式的PWM控制电路D3846- -大电流输出 内置欠压锁定电路 软启动电路

D3846是一块电流模式的PWM控制电路。 主要特点&#xff1a; ● 自动前馈补偿 ● 可编程控制的逐个脉冲限流功能 ● 推挽输出结构^ 下自动对称校正 ● 负载响应特性好 ● 可并联运行&#xff0c;适用于模块系统 ● 内置差动电流检测放大器&#xff0c; 共模输入范围宽 ● 双脉…

【有限元仿真】or【流体仿真】

流体和刚体的关系&#xff1f; 刚体仿真关注刚性物体的运动和力学行为。刚体是指在外力作用下保持形状和结构不变的物体&#xff0c;不受弯曲或拉伸的影响。刚体仿真基于刚体力学原理和刚体运动学方程&#xff0c;模拟刚体的运动、转动、碰撞等行为。它可以用于模拟刚体之间的…

Linux主机自动注册NPS客户端(脚本化)

参考官方对API使用方法的定义&#xff1a;https://ehang-io.github.io/nps/#/ 1、首先必须要在配置文件中开启 auth_key 并配置一个合适的密钥 2、修改脚本中的可变量参数&#xff0c;以适配自己的环境 #!/bin/bash # 脚本使用说明&#xff1a;# 脚本名称&#xff1a;npc_cr…

浏览器中的Python:Brython

简介 将 Python 代码转换为 JavaScript&#xff0c;使我们能够在浏览器中编写和运行 Python 代码。可以实现python和js代码相互调用。基于Python 3 实现&#xff0c;支持HTML5环境&#xff08;提供了DOM对象和事件接口&#xff09;。支持turtle绘图库&#xff0c;可以进行图像…