2020-GKCTF-Reverse
2020-GKCTF
Check_1n
思路一:
查找字符串之后,点击"密码错误"发现了关键,上方的一个strcmp函数,发现了密码:
‘HelloWorld’
我们直接运行一下,然后输入密码开机,之后移动到"flag",结果给了base64编码的Why don’t you try the magic brick game
然后我们玩打砖块游戏,死了之后就出flag
思路二:
查找字符串的时候发现:
2i9Q8AtFJTfL3ahU2XGuemEqZJ2ensozjg1EjPJwCHy4RY1Nyvn1ZE1bZe
点过去之后交叉引用发现了base58的table,直接base58解密得到flag
Chelly’s ldentity
加密函数:
比较函数:
至于为什么知道哪个变量是哪个,动调来看就知道了
WP:
# _*_ coding:utf-8 _*_
# @功能描述:
# @程序作者:SYJ
# @版权信息:Reversed By SYJ
# @版本信息:0.0.0
arr = [0x00000002, 0x00000003, 0x00000005, 0x00000007, 0x0000000B, 0x0000000D, 0x00000011, 0x00000013, 0x00000017, 0x0000001D, 0x0000001F, 0x00000025, 0x00000029, 0x0000002B, 0x0000002F, 0x00000035, 0x0000003B, 0x0000003D, 0x00000043, 0x00000047, 0x00000049, 0x0000004F, 0x00000053, 0x00000059, 0x00000061, 0x00000065, 0x00000067, 0x0000006B, 0x0000006D, 0x00000071, 0x0000007F]
cmp = [0x000001B6, 0x00000498, 0x00000441, 0x00000179, 0x00000179, 0x00000640, 0x0000039C, 0x00000179, 0x0000064A, 0x0000039C, 0x0000027D, 0x0000027F, 0x00000178, 0x00000236, 0x00000344, 0x0000033E]
flag = ''
for i in range(len(cmp)):for x in range(32, 127):su_m = 0for j in arr:if j < x:su_m += jtemp = x ^ su_mif temp == cmp[i]:flag += chr(x)
print('flag{'+flag+'}')
flag{Che11y_1s_EG0IST}
BabyDriver
是一道很经典的键盘过滤驱动,下面几张图是经典的键盘过滤驱动:
我们主要看的就是IRP读操作的回调函数(第二个函数),也就是CompletionRoutine的位置
分析我们的题目:
找到DriverEntry函数中的sub_1400011E0函数
__int64 __fastcall sub_1400011E0(PDRIVER_OBJECT DriverObject)
{DriverObject->DriverUnload = (PDRIVER_UNLOAD)sub_140001260;// 注册驱动卸载函数KdDisableDebugger();memset64(DriverObject->MajorFunction, (unsigned __int64)sub_1400012B0, 27ui64);// 注册通用的IRP分发函数DriverObject->MajorFunction[3] = (PDRIVER_DISPATCH)sub_1400014E0;// 注册读IRP分发函数DriverObject->MajorFunction[22] = (PDRIVER_DISPATCH)&sub_140001340;// 注册电源IRP分发函数DriverObject->MajorFunction[27] = (PDRIVER_DISPATCH)sub_1400012D0;// 注册即插即用IRP分发函数AttachDevice(DriverObject); // 绑定设备return 0i64;
}
点击读IRP分发函数
NTSTATUS __fastcall sub_1400014E0(_QWORD *a1, IRP *a2)
{NTSTATUS result; // eax_DEVICE_OBJECT *v5; // rcx_IO_STACK_LOCATION *v6; // rax_IO_STACK_LOCATION *v7; // raxif ( a2->CurrentLocation == 1 ){a2->IoStatus.Information = 0i64;a2->IoStatus.Status = 0xC0000010;IofCompleteRequest(a2, 0);result = 0xC0000010;}else{v5 = *(_DEVICE_OBJECT **)(a1[8] + 24i64);v6 = a2->Tail.Overlay.CurrentStackLocation;*(_OWORD *)&v6[-1].MajorFunction = *(_OWORD *)&v6->MajorFunction;*(_OWORD *)&v6[-1].Parameters.NotifyDirectoryEx.CompletionFilter = *(_OWORD *)&v6->Parameters.NotifyDirectoryEx.CompletionFilter;*(_OWORD *)(&v6[-1].Parameters.SetQuota + 6) = *(_OWORD *)(&v6->Parameters.SetQuota + 6);v6[-1].FileObject = v6->FileObject;v6[-1].Control = 0;v7 = a2->Tail.Overlay.CurrentStackLocation;v7[-1].Context = a1;v7[-1].CompletionRoutine = (PIO_COMPLETION_ROUTINE)sub_140001380;// 键盘过滤驱动,主要看下IRP读操作的回调函数(第二个函数),也就是CompletionRoutine的位置v7[-1].Control = 0xE0;result = IofCallDriver(v5, a2);}return result;
}
在其中找到CompletionRoutine对应的函数sub_140001380
在其中发现了迷宫
__int64 __fastcall sub_140001380(__int64 a1, __int64 a2)
{__int64 v3; // rdi__int64 v4; // raxint direction; // ecx__int16 *v6; // rsi__int64 v7; // rbp__int16 v8; // dxchar v9; // dlconst CHAR *v10; // rcxif ( *(int *)(a2 + 48) >= 0 ){v3 = *(_QWORD *)(a2 + 24);v4 = *(_QWORD *)(a2 + 56) >> 3;if ( (_DWORD)v4 ){direction = dword_1400030E4; // 初值为16v6 = (__int16 *)(v3 + 2);v7 = (unsigned int)v4;while ( *(_WORD *)(v3 + 4) ){LABEL_28:v6 += 6;if ( !--v7 )goto LABEL_29;}aO[direction] = '.';v8 = *v6;if ( *v6 == 23 ){if ( (direction & 0xFFFFFFF0) != 0 ){direction -= 16; // 上移goto LABEL_21;}direction += 0xD0;dword_1400030E4 = direction;}if ( v8 == 37 ){if ( (direction & 0xFFFFFFF0) != 0xD0 ){direction += 16; // 下移,+16代表下移一行goto LABEL_21;}direction -= 208;dword_1400030E4 = direction;}if ( v8 == 36 ){if ( (direction & 0xF) != 0 ){--direction; // 左移goto LABEL_21;}direction += 15;dword_1400030E4 = direction;}if ( v8 != 38 )goto final;if ( (direction & 0xF) == 15 )direction -= 15;else++direction; // 右移
LABEL_21:dword_1400030E4 = direction;
final:v9 = aO[direction];if ( v9 == '*' ) // 撞墙{v10 = "failed!\n";}else{if ( v9 != '#' ) // 没走到目标'#'{LABEL_27:aO[direction] = 'o'; // 就回到起点goto LABEL_28;}v10 = "success! flag is flag{md5(input)}\n";}dword_1400030E4 = 16;DbgPrint(v10);direction = dword_1400030E4;goto LABEL_27;}}
LABEL_29:if ( *(_BYTE *)(a2 + 'A') )*(_BYTE *)(*(_QWORD *)(a2 + 0xB8) + 3i64) |= 1u;return *(unsigned int *)(a2 + '0');
}
导出迷宫并走出路线:
# _*_ coding:utf-8 _*_
# @功能描述:
# @程序作者:SYJ
# @版权信息:Reversed By SYJ
# @版本信息:0.0.0
maze = "****************o.*..*......*..**.**...**.*.*.***.****.**.*.*.***...**....*.*.*****..***.**.*..**.**.***.**.**.**.**.******.**.**.**....***.**.**.*****.***....**...***.**********..***......#****.*****************************"
for i in range(len(maze)):if (i+1) % 16 == 0:print(maze[i])else:if i != 0:print(maze[i], end=' ')else:print(maze[i], end=' ')
import hashlib
line = "LKKKLLKLKKKLLLKKKLLLLLL"
flag = hashlib.md5(line.encode("utf-8")).hexdigest().lower()
print('flag{'+flag+'}')
flag{403950a6f64f7fc4b655dea696997851}
DbglsFun
打开之后发现了TLS回调函数,会在主线程开始的时候会调用,TLS回调函数的调用要先于EP代码的执行
在其中发现了smc自解密代码:
void __stdcall TlsCallback_0(int a1, int a2, int a3)
{int i; // eaxDWORD flOldProtect; // [esp+0h] [ebp-8h] BYREFif ( a2 == 1 ){VirtualProtect(sub_4010F0, 0x42Eu, 0x40u, &flOldProtect);for ( i = 0; i < 1070; ++i )*((_BYTE *)sub_4010F0 + i) ^= i;CreateThread(0, 0, sub_4010F0, 0, 0, 0);}
}
我们静态的话就写个脚本跑一下这个smc自解密:
addr = 0x004010F0
for i in range(1070):ida_bytes.patch_byte((addr+i), idc.get_wide_byte(addr+i) ^ i)
然后将地址004010F0开始的重新定义为一个函数
很明显的能看出来是先将我们的flag和一个值异或,然后再进行了RC4
最后再进行比较
写出脚本:
/* 注意事项
* 1.明文密文还有状态数组s[i](0-255)的类型应都选择unsigned char类型,因为其取值范围为0-255,一字节
* 2.明文密文以及状态数组s[i]的类型应该全部一样,这样做异或运算时就不会发生内存溢出的问题
*/
#include <stdio.h>
#include <string.h>void rc4_init(unsigned char*s,unsigned char*key,unsigned long len)
{int i=0;int j=0;unsigned char k[256]={};unsigned char temp = 0;for(i=0;i<256;i++){s[i]=i; //0-255赋给sk[i]=key[i%len]; //将k重新计算}for(i=0;i<256;i++){j=(j+s[i]+k[i])%256; //给j赋值temp=s[i];s[i]=s[j];s[j]=temp; //s[i]和s[j]交换}
}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 temp;for(k=0;k<len;k++){i=(i+1)%256; //固定方式生成的ij=(j+s[i])%256; //固定方式生成的jtemp=s[i];s[i]=s[j];s[j]=temp; //交换s[i]和s[j]t=(s[i]+s[j])%256; //固定方式生成的tdata[k]^=s[t]; //来作为s的下标和data进行异或运算}
}int main()
{unsigned char s[256]={0};char key[256] = "GKCTF";unsigned char data[512]={0x2D, 0xD4, 0x0F, 0xD0, 0x54, 0xEE, 0x75, 0xD0, 0xE0, 0x30, 0x96, 0xE1, 0x79, 0x8A, 0xE0, 0xFE, 0x18, 0x3A, 0x27, 0xE7, 0x2F, 0x86, 0xC9, 0xFE, 0x66, 0x43, 0xA7, 0x75};unsigned long data_len = 28;unsigned long key_len = strlen(key);rc4_init(s,(unsigned char*)key,key_len);//初始化得到src4_crypt(s,(unsigned char*)data,data_len);//解密//printf("解密后为:%s",(unsigned char*)data);for(int i=0;i<28;i++){printf("%c",(data[i]^0xC9)&0xff);}return 0;
}
flag{5tay4wayFr0m8reakp0int}
Process returned 0 (0x0) execution time : 0.010 s
Press any key to continue.
EzMachine
写过这个的WP,是一道非常经典的虚拟机,拿来入门很不错的
https://bbs.pediy.com/thread-267670.htm
WannaReverse
题目解压之后得到四个文件,点击clickme.exe会更改壁纸,一个模拟病毒
然后将WannaReverse.exe拖入ida进行分析:
char v9; // [esp-4h] [ebp-40h]__int128 v10[2]; // [esp+8h] [ebp-34h] BYREFchar v11; // [esp+28h] [ebp-14h]char string[12]; // [esp+2Ch] [ebp-10h] BYREFv10[0] = 0i64;v10[1] = 0i64;WinExec("clickme.exe", 1u);strcpy(string, "0123456789");v3 = _time64(0);srand(v3);for ( i = 0; i < 32; ++i )*((_BYTE *)v10 + i) = string[rand() % 10]; // rand() % 10// [0-10)取随机数v9 = v5;v11 = 0;v6 = encrypt(v5, v10); // 随机生成的长度为32的v9v7 = "encrypto success!";if ( !v6 )v7 = "encrypto false!";printf((int)v7, v9);return 0;
}
它先运行了一下clickme.exe,然后在[0-10)取随机数用来当作下标,生成一个随机的长度为32的字符串(后面可以知道这个就是我们AES的密钥)
进入encrypt函数分析:
首先打开了flag.txt
然后中间一截就是用AES加密目标文件flag.txt之后加了个后缀.Encry
然后将使用RSA加密后的AES密钥放在了文件flag.txt.Encry
这就是那个flag.txt.Encry的由来
解题思路:
在WannaReverse.exe中找到RSA公钥:
然后在clickme.exe中找到私钥:
在线解密RSA
https://oktools.net/rsa
得到:30776159143604297789676442413079
然后写个脚本将flag.txt.Encry的剩下部分进行AES解密即可
# _*_ coding:utf-8 _*_
# @功能描述:
# @程序作者:SYJ
# @版权信息:Reversed By SYJ
# @版本信息:0.0.0
from Crypto.Cipher import AES
mode = AES.MODE_ECB # 规定是ECB的加密模式
key = b"30776159143604297789676442413079"
cryptos = AES.new(key, mode) # 传入key形成加解密函数
en_flag = [0x5C, 0xBC, 0xEA, 0x89, 0xBA, 0x2B, 0x18, 0x27, 0x79,0x3F, 0x13, 0x0A, 0x8A, 0x97, 0xB4, 0x9B, 0xCD, 0x78,0x9B, 0xD8, 0x35, 0x92, 0x05, 0x45, 0x4C, 0x22, 0xA5,0x69, 0x37, 0xEB, 0x6E, 0x2B, 0x0E, 0xBD, 0x84, 0x0F,0x91, 0x61, 0x38, 0xF6, 0xF1, 0xBA, 0x99, 0x19, 0x41,0x72, 0x07, 0x91, 0xF0, 0x26, 0x68, 0x06, 0x61, 0x26,0x5C, 0x20, 0x35, 0xDD, 0xCF, 0xFC, 0x77, 0x57, 0x54,0x81, 0xF2, 0xF2, 0xE4, 0xAF, 0xBF, 0xA2, 0x1D, 0x29,0xAE, 0x6C, 0x08, 0x3B, 0x76, 0x1B, 0x66, 0xB8, 0xFE,0x72, 0xCB, 0xD6, 0x94, 0xC3, 0xD5, 0x6A, 0xE7, 0x0C,0x7A, 0x28, 0xDC, 0xBC, 0xAC, 0x80]
bytes_flag = cryptos.decrypt(bytes(en_flag)) # 直接进行解密
print(bytes_flag)# b'\xff\xfef\x00l\x00a\x00g\x00{\x003\x008\x005\x00f\x00a\x008\x006\x009\x00-\x003\x000\x004\x006\x00-\x004\x004\x00e\x00e\x00-\x009\x00d\x003\x000\x00-\x00c\x000\x003\x005\x005\x001\x002\x007\x003\x008\x006\x007\x00}\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
# flag{385fa869-3046-44ee-9d30-c03551273867}
2020-GKCTF-Reverse相关推荐
- 2020-2021 ICPC Southeastern European Regional Programming Contest (SEERC 2020)
2020-2021 ICPC Southeastern European Regional Programming Contest (SEERC 2020) B. Reverse Game 题目描述: ...
- BUUCTF Reverse/[网鼎杯 2020 青龙组]jocker
BUUCTF Reverse/[网鼎杯 2020 青龙组]jocker 先看下文件信息,没有加壳,32位程序 运行一下,又是一道字符串比较的题目 用IDA32位打开,分析一下 // positive ...
- [BUGKU][CTF][Reverse][2020] Reverse writeup 1-7 暂时肝不动了
Reverse 入门逆向 步骤: ida main函数 按R Reverse signin 关键字: 知识点:Android逆向分析.(常用工具:安卓模拟器.JEB.Cyberchef.Android ...
- [BUUCTF]Reverse——[网鼎杯 2020 青龙组]jocker
网上大部分是动调,我尝试IDC解一下, 无壳,32位,放入IDApro,查看main函数 查看wrong和str函数,借出假的flag a=[0x66,0x6B,0x63,0x64,0x7F,0x61 ...
- BUUCTF Reverse/[羊城杯 2020]easyre
查看信息,无壳,64位程序 IDA打开分析代码,又是一个字符串比较的问题,输入flag,对flag加密三次,flag的长度为38 int __cdecl main(int argc, const ch ...
- BUUCTF reverse题解汇总
本文是BUUCTF平台reverse题解的汇总 题解均来自本人博客 目录 Page1 Page2 Page3 Page4 Page1 easyre reverse1 reverse2 内涵的软件 新年 ...
- QIIME 2教程. 09数据导入Importing data(2020.11)
文章目录 QIIME 2用户文档. 9数据导入 导入带质量值的FASTQ测序数据 EMP标准混样单端数据 EMP混样双端数据 Casava1.8单端混样数据 Casava 1.8双端拆分后数据 **F ...
- QIIME 2教程. 03老司机上路指南Experience(2020.11)
文章目录 老司机上路指南 本节视频视频教程 为什么要改用QIIME 2? 老司机上路前的几点建议 数据处理步骤 数据导入 样本拆分 双端合并 去除非生物序列 相似序列分组 去噪 OTU聚类 物种分类 ...
- 报名即将关闭丨AAAI 2020论文预讲会
AAAI 2020 论文预讲会,来啦! 30多位论文作者,来自五湖四海,齐聚北大.预会议内容方向包括:翻译对话与生成.文本分析与内容挖掘.知识理解与NLP应用.自然语言中的机器学习等,此外还有两场特邀 ...
- 2020上的NLP有哪些研究风向?
点击上方"AI遇见机器学习",选择"星标"公众号 重磅干货,第一时间送达 作者 | Camel 编辑 | 十.年 来源 | AI科技评论 距离 AAAI 202 ...
最新文章
- 《Hadoop实战手册》一1.6 配置Sqoop以支持SQL Server
- 转自CSDNattilax的专栏 :自适应网页设计 跟 响应式 设计的区别跟原理and实践总结...
- python有趣的工具_python好玩的小工具(正在create中)
- 求中位数中回文数之和C语言,一些算法题及答案
- 无处不在_Java无处不在:使用DukeScript在任何地方运行一次编写
- python regex_Python 正则表达式
- linux安装nginx、php
- Docker折腾手记-安装
- 人人都在讲数据治理而不问业务,这很危险
- 将ubuntu的home迁移至第二块磁盘
- Android中如何实现无缝切码流
- java小程序实例大全_12个用Java编写基础小程序经典案例(收藏)
- 软考/软件设计师资料真题/软件设计师教程
- flash绘制荷花多个图层_《荷花》Flash动画课件
- chromecast 协议_如何更改您的Chromecast的设备名称
- unity3d多人寻路问题方案
- SNH48周边商品抢购分析
- ThreeJS后期处理
- 十分钟掌握 “UML ” 的基本使用
- Day1:Angry young women: A new generation of activists is challenging misogyny
热门文章
- Eclipse中使用SQL server 2008数据库以及实现eclipse与数据库的连接和操作数据库
- vs2019新手怎么解决命名空间“”中不存在类型或命名空间名“”(是否缺少程序集引用?)问题全解
- 区块链火了 市场热度最么高
- 以德治国——《万历十五年》的读书笔记及读后感想2900字
- 2.深入解析Javascript异步编程
- Cannot find module ‘node-sass‘问题解决
- 红帽linux9.0安装教程,红帽linux9.0安装教程
- vue从零搭建一个前中后台权限管理模板
- maven编译,执行测试用例报错 The forked VM terminated without saying properly goodbye. VM crash or System.exit c
- Android webview 播放视频及全屏