攻防世界:crypt(RC4)

news2024/12/27 10:45:40

1、下载

PE文件,控制台程序

2、main函数

大致分析,请看下面的注释

int __cdecl main(int argc, const char **argv, const char **envp)
{
  unsigned int str_length; // eax
  unsigned int myflag_length; // eax
  void *v5; // rax
  void *v7; // rax
  int i; // [rsp+24h] [rbp-D4h]
  void *memory; // [rsp+28h] [rbp-D0h]
  char myflag[32]; // [rsp+30h] [rbp-C8h] BYREF
  char Str[128]; // [rsp+50h] [rbp-A8h] BYREF

  strcpy(Str, "12345678abcdefghijklmnopqrspxyz");
  memset(&Str[32], 0, 0x60ui64);
  memset(myflag, 0, 0x17ui64);
  sub_1400054D0("%s", myflag);                  // 输入字符串
  memory = malloc(0x408ui64);                   // v9应该是一个内存地址,是申请下来的地址
  str_length = strlen(Str);
  sub_140001120(memory, Str, str_length);       // 关键
  myflag_length = strlen(myflag);
  sub_140001240(memory, myflag, myflag_length); // 关键
  for ( i = 0; i < 22; ++i )
  {
    if ( ((unsigned __int8)myflag[i] ^ 0x22) != main_break[i] )// 加密之后的myflag[i]^0x22=main_break[i]
    {
      v5 = (void *)sub_1400015A0(&off_14013B020, "error");// 输出错误
      _CallMemberFunction0(v5, sub_140001F10);
      return 0;
    }
  }
  v7 = (void *)sub_1400015A0(&off_14013B020, "nice job");// 正确
  _CallMemberFunction0(v7, sub_140001F10);
  return 0;
}

sub_140001120函数和sub_140001240函数看起来很重要

提取main_break[]数组

unsigned char main_break[] =
{
  0x9E, 0xE7, 0x30, 0x5F, 0xA7, 0x01, 0xA6, 0x53, 0x59, 0x1B, 
  0x0A, 0x20, 0xF1, 0x73, 0xD1, 0x0E, 0xAB, 0x09, 0x84, 0x0E, 
  0x8D, 0x2B, 0x00, 0x00
};

3、sub_140001120函数

__int64 __fastcall sub_140001120(_DWORD *a1, __int64 key, int key_length)
{
  __int64 result; // rax
  int i; // [rsp+0h] [rbp-28h]
  int j; // [rsp+0h] [rbp-28h]
  int v6; // [rsp+4h] [rbp-24h]
  int v7; // [rsp+8h] [rbp-20h]
  int tmp; // [rsp+Ch] [rbp-1Ch]
  _DWORD *s_box; // [rsp+10h] [rbp-18h]

  *a1 = 0;
  a1[1] = 0;
  s_box = a1 + 2;    			//给s_box放在堆空间里面
  for ( i = 0; i < 256; ++i )
    s_box[i] = i;                               // 给 v9数组初始化 0~255
  v6 = 0;
  result = 0i64;
  LOBYTE(v7) = 0;
  for ( j = 0; j < 256; ++j )
  {                                         // 下面这一段是RC4加密,v8是临时变量,进行交换
    tmp = s_box[j];
    v7 = (key[v6] + tmp + v7);            // Key[v6]+tmp+v7
    s_box[j] = s_box[v7];
    s_box[v7] = tmp;
    if ( ++v6 >= key_length )                   // v6下标在规定范围内255循环
      v6 = 0;                                   // 重置为0
    result = (unsigned int)(j + 1);
  }
  return result;                                // 返回一个result
}

可以得出结论,sub_140001120是re4_init函数

Str="12345678abcdefghijklmnopqrspxyz" 是key

4、sub_140001240函数

那么这个函数就是RC4加密函数了,稍微分析了一下,发现写的代码很妙啊

_DWORD *__fastcall sub_140001240(_DWORD *memory, __int64 myflag, int myflag_length)
{
  _DWORD *result; // rax
  int i; // [rsp+0h] [rbp-28h]
  int tmp1; // [rsp+4h] [rbp-24h]
  int tmp2; // [rsp+8h] [rbp-20h]
  int v7; // [rsp+Ch] [rbp-1Ch]
  int v8; // [rsp+10h] [rbp-18h]
  _DWORD *s_box; // [rsp+18h] [rbp-10h]

  tmp1 = *memory;
  tmp2 = memory[1];
  s_box = memory + 2;
  for ( i = 0; i < myflag_length; ++i )
  {                                             // 这段RC4写的很妙啊
    tmp1 = (unsigned __int8)(tmp1 + 1);
    v7 = s_box[tmp1];
    tmp2 = (unsigned __int8)(v7 + tmp2);
    v8 = s_box[tmp2];
    s_box[tmp1] = v8;                           // 交换s_box盒
    s_box[tmp2] = v7;
    *(_BYTE *)(myflag + i) ^= LOBYTE(s_box[(unsigned __int8)(v8 + v7)]);// myflag[i] ^=s_box[v8+v7]
  }
  *memory = tmp1;
  result = memory;
  memory[1] = tmp2;
  return result;
}

5、解题

网上找一下RC4的解题脚本,做RC4这类题,只要找到密文key,就可以做出来

flag1=[]
main_break=[0x9E, 0xE7, 0x30, 0x5F, 0xA7, 0x01, 0xA6, 0x53, 0x59, 0x1B,0x0A, 0x20, 0xF1, 0x73, 0xD1, 0x0E, 0xAB, 0x09, 0x84, 0x0E,0x8D, 0x2B, 0x00, 0x00]
for i in range(len(main_break)):
    flag1.append(main_break[i]^0x22)
#flag1是经过rc4加密后的值
#现在有 flag1 和 rc4 key
#输出
flag1= [188, 197, 18, 125, 133, 35, 132, 113, 123, 57, 40, 2, 211, 81, 243, 44, 137, 43, 166, 44, 175, 9, 34, 34]
#include<stdio.h>
#include<string.h>
typedef unsigned longULONG;

/*初始化函数*/
void rc4_init(unsigned char*s, unsigned char*key, unsigned long Len)
{
	int i = 0, j = 0;
	char k[256] = { 0 };
	unsigned char tmp = 0;
	for (i = 0; i < 256; i++)
	{
		s[i] = i;
		k[i] = key[i%Len];
	}
	for (i = 0; i < 256; i++)
	{
		j = (j + s[i] + k[i]) % 256;
		tmp = s[i];
		s[i] = s[j]; // 交换s[i]和s[j]
		s[j] = tmp;
	}
}

/*加解密*/
void rc4_crypt(unsigned char*s, unsigned char*Data, unsigned long Len)
{
	int i = 0, j = 0, t = 0;
	unsigned long k = 0;
	unsigned char tmp;
	for (k = 0; k < Len; k++)
	{
		i = (i + 1) % 256;
		j = (j + s[i]) % 256;
		tmp = s[i];
		s[i] = s[j]; // 交换s[x]和s[y]
		s[j] = tmp;
		t = (s[i] + s[j]) % 256;
		Data[k] ^= s[t];
	}
}

int main()
{
	unsigned char s[256] = { 0 }, s2[256] = { 0 }; // S-box
	char key[256] = { "12345678abcdefghijklmnopqrspxyz" };
	char pData[] = {0xbc,0xc5,0x12,0x7d,0x85,0x23,0x84,0x71,0x7b,0x39,0x28,0x2,0xd3,0x51,0xf3,0x2c,0x89,0x2b,0xa6,0x2c,0xaf,0x9,0x22,0x22};
	  
	unsigned long len = strlen(pData);
	int i;

	printf("pData=%s\n", pData);
	printf("key=%s,length=%d\n\n", key, strlen(key));
    
	rc4_init(s, (unsigned char*)key, strlen(key)); // 已经完成了初始化
	printf("\n\n");
	for (i = 0; i < 256; i++) // 用s2[i]暂时保留经过初始化的s[i],很重要的!!!
	{
		s2[i] = s[i];
	}
    
    //可以看到,加解密函数都是相同的
	printf("已经加密,现在解密:\n\n");
	rc4_crypt(s2, (unsigned char*)pData, len); // 解密
	printf("pData=%s\n\n", pData);
	return 0;
}

key= 12345678abcdefghijklmnopqrspxyz

flag{nice_to_meet_you}

6、总结

收获很大,深刻理解RC4,搞到了解RC4的两套方法

第一种:脚本解密

第二种:获得RC4后的数据,输入flag,进行动态调试,直接逆出flag

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软测(概念) · 开发模型 · 软件的生命周期 · 瀑布模型 · 螺线模型 · 增量模型 · 迭代模型 · 敏捷模型 · scrum · 软件测试模型之 V 模型 W 模型

一、开发模型的由来二、软件的生命周期三、瀑布模型&#xff08;Waterfall Model&#xff09;四、螺线模型&#xff08;Spiral Model&#xff09;五、增量模型&#xff08;Incremental Model&#xff09;六、迭代模型&#xff08;Rational UnifiedProcess&#xff09;七、敏捷模…

SQL Server 2014 数据库误删数据的恢复处理

一、序言 作为程序开发人员或 DBA&#xff0c;经常会接触到数据库&#xff08;以 SQL Server 2014 数据库为例&#xff09;的增、删、改查操作。执行 delete 语句时不小心误删数据表的记录情况&#xff0c;而数据库之前又没有任何备份。 SQL Server 数据库自身的数据库还原数…

使用蚁群优化 (ACO) 解决背包问题(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 背包问题&#xff08;Knapsack problem&#xff09;是一种组合优化的NP完全&#xff08;NP-Complete&#xff0c;NPC&#xff0…

【My Electronic Notes系列——组合逻辑电路】

目录 序言&#xff1a; &#x1f3c6;&#x1f3c6;人生在世&#xff0c;成功并非易事&#xff0c;他需要破茧而出的决心&#xff0c;他需要永不放弃的信念&#xff0c;他需要水滴石穿的坚持&#xff0c;他需要自强不息的勇气&#xff0c;他需要无畏无惧的凛然。要想成功&…

【页面设计】03.JavaScript

一、什么是JavaScript&#xff1f; 一种编程语言&#xff0c;可以在网页上实现复杂的功能、交互等。是一种解释型语言&#xff0c;也是一种面向对象的语言。 ps&#xff1a;解释型语言&#xff0c;是在运行的时候将程序翻译成机器语言。解释型语言的程序不需要在运行前编译&a…

怎么找回删除的文件?尝试下这些恢复数据的方法

我们使用电脑时&#xff0c;总会产生各种各样的文件数据。这些文件保存在电脑里面&#xff0c;但是有时不免手滑误删重要的文件。这些文件被删除、被清空了&#xff0c;还可以恢复回来吗&#xff1f;怎么找回删除的文件&#xff1f;建议你尝试下这些恢复数据的方法。 一、文件恢…

一篇了解Eureka

文章目录一.Eureka注册中心1.1.Eureka简介1.2.Eureka基本架构1.2.1 EurekaServer(注册中心)1.2.2 EurekaClient(客户端)二.Eureka项目的构建2.1 新建一个工程EurekaServer-70012.2.将user-service注册到Eureka2.3 消费者从Eureka获取服务2.4.注册微服务信息完善三、CAP理论3.1.…

ITK多线程加速filter

文章目录1. ITK多线程简介1.1 平台多线程1.1.1 基本内容1.1.2 Intel的TBB1.2 典型例子&#xff08;执行原理&#xff09;1.3 5.X版本之后的变动1.4 ITK多线程整体认识1.4.1 基本内容1.4.2 过滤器级别的多线程&#xff08;Filter Level Multithreading&#xff09;1.4.3 内存管理…

Shader绘制2D圆-学习Cherno教程笔记-(OpenGL/Vulkan/DirectX/Metal)-新手向

文章目录相关网址前言基本实现画一个圆步骤1.初步-根据长度绘画圆2.初步-根据1-length(uv)绘画圆3.正式-绘画白色形状的圆(1)if逻辑代码实现(2)用shader的step函数完善圆-实现绘画手环圆1.if逻辑代码实现2.用step函数代替if用smoothstep代替step函数1.smoothstep函数2.使用smoo…

ESP-IDF:使用STL stack栈做检查括号是否匹配测试

ESP-IDF:使用STL stack栈做检查括号是否匹配测试 /使用栈检查括号是否匹配测试/ #include typedef struct LINKNODE20 { struct LINKNODE20 * next; }linknode20; typedef struct MYCHAR20 { linknode20 node; char * address; int index; }MyChar20; MyChar20 * createMyC…

【MFC】文档操作——范例(12)

使用MFC框架文档操作范例&#xff1a; 创建工程 创建工程&#xff0c;其中&#xff1a; 1、MFC单文档 2、自定义改应用程序数据文件扩展名&#xff1a; 3、 最后一步选择CListView&#xff08;用报表显示数据&#xff09; 重点问题&#xff1a;数据文件的读写功能 添加数据类…

电脑多个不同分辨率屏幕鼠标移动时出现偏移、错位情况的解决方法

本文介绍在使用不同尺寸、不同分辨率的两个或多个电脑屏幕时&#xff0c;鼠标在不同屏幕之间切换时&#xff0c;出现偏移、飘动、不规则运动等情况的解决方法。 对于使用两个或多个电脑屏幕的用户而言&#xff0c;鼠标在不同屏幕之间的切换有时候会出现偏移的问题。在同时使用多…

【My Electronic Notes系列——逻辑函数的化简】

目录 序言&#xff1a; &#x1f3c6;&#x1f3c6;人生在世&#xff0c;成功并非易事&#xff0c;他需要破茧而出的决心&#xff0c;他需要永不放弃的信念&#xff0c;他需要水滴石穿的坚持&#xff0c;他需要自强不息的勇气&#xff0c;他需要无畏无惧的凛然。要想成功&…

MySQL入门篇-MySQL字符集小结

备注:测试数据库版本为MySQL 8.0 这个blog我们来聊聊MySQL的字符集 前言: 字符集和排序规则 说实话我对这两个概念比较模糊&#xff0c;其实可以简单的理解: 字符集(character set)&#xff1a;定义了字符以及字符的编码。 排序规则(collation)&#xff1a;定义了字符的比…

【Django】ORM增删改查、F对象和Q对象、聚合操作和原生数据库操作

1、ORM的增删改查均需要通过管理器对象进行。 2、可使用python3 manage.py shell 进入脚本页方便操作。 3、可修改输出格式 一、ORM查询操作 1、查询方法 &#xff08;1&#xff09;all()方法 用法&#xff1a;MyModel.objects.all()作用&#xff1a;查询所有数据&#xff0c…

微信小程序——自定义组件(纯数据字段),组件的生命周期,组件所在页面的生命周期,插槽,父子组件之间的通信,事件绑定,属性绑定,behavior

一.纯数据字段1.什么是纯数据字段概念&#xff1a;纯数据字段指的是那些不用于界面渲染的data字段。应用场景&#xff1a;例如有些情况下&#xff0c;某些 data 中的字段既不会展示在界面上&#xff0c;也不会传递给其他组件&#xff0c;仅仅在当前组件内部使用。带有这种特性的…

《Keras深度学习:入门、实战与进阶》之回归问题实例:波士顿房价预测

本文摘自《Keras深度学习&#xff1a;入门、实战与进阶》。 本节将要预测20世纪70年代中期波士顿郊区房屋价格的中位数。这个数据是1978年统计收集的&#xff0c;数据集中的每一行数据都是对波士顿周边或城镇房价的描述&#xff0c;包含以下14个特征和506条数据。  CRIM&am…

verilog图像算法实现和仿真(代码与实践)

【声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 这里的代码指的是verilog代码,而不是之前的python代码。因为verilog处理的是数据,所以之前我们也谈到过,如果需要用verilog处理图像数据,需要先用python把图像变成文本文件,等到…

菜鸟的进阶--手写一个微型Spring

前言想干嘛深入了解spring原理&#xff0c;特别是IOC容器是如何实现的&#xff1f;AOP是如何实现的&#xff1f;手写一个spring迷你版框架&#xff0c;实现容器和AOP机制。我为什么想这么做spring是整个java体系中最重要的框架&#xff0c;它整合第三方技术&#xff0c;将所有的…

交联剂134272-64-3,Maleimide-NH2 HCl,2-马来酰亚胺乙胺盐酸盐

【中文名称】N-(2-氨乙基)马来酰亚胺盐酸盐&#xff0c;2-马来酰亚胺乙胺盐酸盐【英文名称】 MAL-NH2 HCl&#xff0c;Maleimide-NH2 HCl&#xff0c;MAL NH2 HCl&#xff0c;Maleimide-amine HCl&#xff0c;MAL-amine HCl&#xff0c;N-(2-AMinoethyl)MaleiMide Hydrochlorid…