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相关推荐

  1. 2020-2021 ICPC Southeastern European Regional Programming Contest (SEERC 2020)

    2020-2021 ICPC Southeastern European Regional Programming Contest (SEERC 2020) B. Reverse Game 题目描述: ...

  2. BUUCTF Reverse/[网鼎杯 2020 青龙组]jocker

    BUUCTF Reverse/[网鼎杯 2020 青龙组]jocker 先看下文件信息,没有加壳,32位程序 运行一下,又是一道字符串比较的题目 用IDA32位打开,分析一下 // positive ...

  3. [BUGKU][CTF][Reverse][2020] Reverse writeup 1-7 暂时肝不动了

    Reverse 入门逆向 步骤: ida main函数 按R Reverse signin 关键字: 知识点:Android逆向分析.(常用工具:安卓模拟器.JEB.Cyberchef.Android ...

  4. [BUUCTF]Reverse——[网鼎杯 2020 青龙组]jocker

    网上大部分是动调,我尝试IDC解一下, 无壳,32位,放入IDApro,查看main函数 查看wrong和str函数,借出假的flag a=[0x66,0x6B,0x63,0x64,0x7F,0x61 ...

  5. BUUCTF Reverse/[羊城杯 2020]easyre

    查看信息,无壳,64位程序 IDA打开分析代码,又是一个字符串比较的问题,输入flag,对flag加密三次,flag的长度为38 int __cdecl main(int argc, const ch ...

  6. BUUCTF reverse题解汇总

    本文是BUUCTF平台reverse题解的汇总 题解均来自本人博客 目录 Page1 Page2 Page3 Page4 Page1 easyre reverse1 reverse2 内涵的软件 新年 ...

  7. QIIME 2教程. 09数据导入Importing data(2020.11)

    文章目录 QIIME 2用户文档. 9数据导入 导入带质量值的FASTQ测序数据 EMP标准混样单端数据 EMP混样双端数据 Casava1.8单端混样数据 Casava 1.8双端拆分后数据 **F ...

  8. QIIME 2教程. 03老司机上路指南Experience(2020.11)

    文章目录 老司机上路指南 本节视频视频教程 为什么要改用QIIME 2? 老司机上路前的几点建议 数据处理步骤 数据导入 样本拆分 双端合并 去除非生物序列 相似序列分组 去噪 OTU聚类 物种分类 ...

  9. 报名即将关闭丨AAAI 2020论文预讲会

    AAAI 2020 论文预讲会,来啦! 30多位论文作者,来自五湖四海,齐聚北大.预会议内容方向包括:翻译对话与生成.文本分析与内容挖掘.知识理解与NLP应用.自然语言中的机器学习等,此外还有两场特邀 ...

  10. 2020上的NLP有哪些研究风向?

    点击上方"AI遇见机器学习",选择"星标"公众号 重磅干货,第一时间送达 作者 | Camel 编辑 | 十.年 来源 | AI科技评论 距离 AAAI 202 ...

最新文章

  1. 《Hadoop实战手册》一1.6 配置Sqoop以支持SQL Server
  2. 转自CSDNattilax的专栏 :自适应网页设计 跟 响应式 设计的区别跟原理and实践总结...
  3. python有趣的工具_python好玩的小工具(正在create中)
  4. 求中位数中回文数之和C语言,一些算法题及答案
  5. 无处不在_Java无处不在:使用DukeScript在任何地方运行一次编写
  6. python regex_Python 正则表达式
  7. linux安装nginx、php
  8. Docker折腾手记-安装
  9. 人人都在讲数据治理而不问业务,这很危险
  10. 将ubuntu的home迁移至第二块磁盘
  11. Android中如何实现无缝切码流
  12. java小程序实例大全_12个用Java编写基础小程序经典案例(收藏)
  13. 软考/软件设计师资料真题/软件设计师教程
  14. flash绘制荷花多个图层_《荷花》Flash动画课件
  15. chromecast 协议_如何更改您的Chromecast的设备名称
  16. unity3d多人寻路问题方案
  17. SNH48周边商品抢购分析
  18. ThreeJS后期处理
  19. 十分钟掌握 “UML ” 的基本使用
  20. Day1:Angry young women: A new generation of activists is challenging misogyny

热门文章

  1. Eclipse中使用SQL server 2008数据库以及实现eclipse与数据库的连接和操作数据库
  2. vs2019新手怎么解决命名空间“”中不存在类型或命名空间名“”(是否缺少程序集引用?)问题全解
  3. 区块链火了 市场热度最么高
  4. 以德治国——《万历十五年》的读书笔记及读后感想2900字
  5. 2.深入解析Javascript异步编程
  6. Cannot find module ‘node-sass‘问题解决
  7. 红帽linux9.0安装教程,红帽linux9.0安装教程
  8. vue从零搭建一个前中后台权限管理模板
  9. maven编译,执行测试用例报错 The forked VM terminated without saying properly goodbye. VM crash or System.exit c
  10. Android webview 播放视频及全屏