buu [MRCTF2020]EasyCpp
上次没写出,这次认真分析了一下,发现自己的调试水平也有了上涨,也看了一些C++逆向的文章,尤其是stl,发现C++的oop还是挺复杂,这题还没考啥虚函数的还行了。
一.拖入ida,找到主函数,还是挺容易的
int __cdecl main(int argc, const char **argv, const char **envp)
{
double v3; // xmm0_8
__int64 v4; // rax
__int64 v5; // rcx
__int64 v6; // r8
__int64 v7; // r9
__int64 v8; // rbx
__int64 v9; // rax
int v10; // ebx
__int64 v11; // rax
__int64 v12; // rax
__int64 v13; // rax
__int64 v14; // rax
__int64 v15; // rax
__int64 v16; // rax
char v18; // [rsp+0h] [rbp-140h]
__int64 v19; // [rsp+28h] [rbp-118h]
__int64 v20; // [rsp+30h] [rbp-110h]
int v21; // [rsp+3Ch] [rbp-104h]
char v22; // [rsp+40h] [rbp-100h]
char v23; // [rsp+60h] [rbp-E0h]
char v24; // [rsp+90h] [rbp-B0h]
char v25; // [rsp+AFh] [rbp-91h]
char v26; // [rsp+B0h] [rbp-90h]
char v27; // [rsp+DFh] [rbp-61h]
char v28; // [rsp+E0h] [rbp-60h]
int v29; // [rsp+104h] [rbp-3Ch]
char *v30; // [rsp+108h] [rbp-38h]
int *v31; // [rsp+110h] [rbp-30h]
_DWORD *v32; // [rsp+118h] [rbp-28h]
int *v33; // [rsp+120h] [rbp-20h]
int i; // [rsp+128h] [rbp-18h]
int v35; // [rsp+12Ch] [rbp-14h]
v35 = 0;
std::vector<int,std::allocator<int>>::vector(&v24, argv, envp);
std::vector<bool,std::allocator<bool>>::vector(&v23);
std::allocator<char>::allocator(&v25);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(&v22, &unk_500E, &v25);
std::allocator<char>::~allocator(&v25);
v4 = std::operator<<<std::char_traits<char>>(&std::cout, "give me your key!");
std::ostream::operator<<(v4, &std::endl<char,std::char_traits<char>>);
for ( i = 0; i <= 8; ++i )
{
std::istream::operator>>(&std::cin, &keys[i]);
std::__cxx11::to_string((std::__cxx11 *)&v26, keys[i], (unsigned int)keys[i], v5, v6, v7);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator+=(&v22, &v26);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(&v26);// 输入9组字符
}
v32 = keys;
v33 = keys;
v31 = (int *)&unk_83E4;
while ( v33 != v31 )
{
v21 = *v33;
std::vector<int,std::allocator<int>>::push_back(&v24, &v21);
++v33;
} // 将输入的字符串存入vector中
v8 = std::vector<int,std::allocator<int>>::end(&v24);
v9 = std::vector<int,std::allocator<int>>::begin(&v24);
std::for_each<__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>,main::{lambda(int &)#1}>(// 每组异或1
v8,
v9,
v8);
v30 = &v24;
v20 = std::vector<int,std::allocator<int>>::begin(&v24);
v19 = std::vector<int,std::allocator<int>>::end(v30);// 类似头指针和尾指针
while ( (unsigned __int8)__gnu_cxx::operator!=<int *,std::vector<int,std::allocator<int>>>(&v20, &v19) )
{
v29 = *(_DWORD *)__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>::operator*(&v20);
std::allocator<char>::allocator(&v27);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(&v18, &unk_500E, &v27);// 定义string
std::allocator<char>::~allocator(&v27);
depart(v29, (__int64)&v18, v3); // 一波骚操作
{lambda(std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>> &)#1}::operator()(
(__int64)&func, // 一波替换
(__int64)&v18);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(&v28, &v18);// string复制
v10 = (unsigned __int64){lambda(std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>,int)#2}::operator()(
(__int64)&check, // 比较函数
(__int64)&v28,
v35) ^ 1;
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(&v28);
if ( (_BYTE)v10 )
{
v11 = std::operator<<<std::char_traits<char>>(&std::cout, "Wrong password!");
std::ostream::operator<<(v11, &std::endl<char,std::char_traits<char>>);
system("pause");
exit(0);
}
++v35;
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(&v18);
__gnu_cxx::__normal_iterator<int *,std::vector<int,std::allocator<int>>>::operator++(&v20);// 头指针加一
}
v12 = std::operator<<<std::char_traits<char>>(&std::cout, "right!");
std::ostream::operator<<(v12, &std::endl<char,std::char_traits<char>>);
v13 = std::operator<<<std::char_traits<char>>(&std::cout, "flag:MRCTF{md5(");
v14 = std::operator<<<char,std::char_traits<char>,std::allocator<char>>(v13, &v22);
v15 = std::operator<<<std::char_traits<char>>(v14, ")}");
std::ostream::operator<<(v15, &std::endl<char,std::char_traits<char>>);
v16 = std::operator<<<std::char_traits<char>>(
&std::cout,
"md5()->{32/upper case/put the string into the function and transform into md5 hash}");
std::ostream::operator<<(v16, &std::endl<char,std::char_traits<char>>);
system("pause");
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(&v22);
std::vector<bool,std::allocator<bool>>::~vector(&v23);
std::vector<int,std::allocator<int>>::~vector(&v24);
return 0;
}
把我的分析都写在注释里了,发现这个程序大体的逻辑是,输入9个数字,每个数字异或1,之后,遍历每个数字,进过depart函数,再进行替换,flag里面包含是md5加密的输入的9个数字。这里比较坑的有几点:
1.
当时一直没找到这个函数在哪。。原来点击那个Lambda就可以进入函数中了,lambda之前也百度了一下,之前一道加密题也碰到过,不过是python的语法,C++里面这个和python里面意思大体一致,相当于一个匿名函数,在主函数体里面定义,()里面是指的捕捉对象,具体,用的时候,再回忆。
2.
depart函数,这个递归感觉会劝退很多人,这个函数意思就是将数字分解,最后将除数和最后一个数字拼接成字符串。
二.根据我们的思路逆向写出一个脚本,最后的数字找个在线网站直接加密下就好了。
strs=["=zqE=z=z=z","=lzzE","=ll=T=s=s=E","=zATT","=s=s=s=E=E=E","=EOll=E","=lE=T=E=E=E","=EsE=s=z","=AT=lE=ll"]
def replacediy(str):
str=str.replace("O","0")
str=str.replace("l","1")
str=str.replace("z","2")
str=str.replace("E","3")
str=str.replace("A","4")
str=str.replace("s","5")
str=str.replace("G","6")
str=str.replace("T","7")
str=str.replace("B","8")
str=str.replace("q","9")
str=str.replace("="," ")
return str
flag=""
for i in strs:
tmp=replacediy(i).split(" ")[1:]
print tmp
sum=1
for j in range(len(tmp)):
sum*=int(tmp[j],10)
sum^=1
flag+=str(sum)
print flag
buu [MRCTF2020]EasyCpp的更多相关文章
- buu [MRCTF2020]keyboard
密文: ooo yyy ii w uuu ee uuuu yyy uuuu y w uuu i i rr w i i rr rrr uuuu rrr uuuu t ii uuuu i w u rrr ...
- Buu刷题
前言 希望自己能够更加的努力,希望通过多刷大赛题来提高自己的知识面.(ง •_•)ง easy_tornado 进入题目 看到render就感觉可能是模板注入的东西 hints.txt给出提示,可以看 ...
- BUU刷题01
[安洵杯 2019]easy_serialize_php 直接给了源代码 <?php $function = @$_GET['f']; function filter($img){ $filte ...
- buu学习记录(上)
前言:菜鸡误入buu,差点被打吐.不过学到了好多东西. 题目名称: (1)随便注 (2)高明的黑客 (3)CheckIn (4)Hack World (5)SSRF Me (6)piapiapia ( ...
- [BUUCTF]REVERSE——[MRCTF2020]hello_world_go
[MRCTF2020]hello_world_go 附件 步骤: 例行检查,64位程序,无壳 64位ida载入,检索程序里的字符串,有很多,直接检索flag 一个一个点过去,找到了flag 按a,提取 ...
- [BUUCTF]REVERSE——[MRCTF2020]Xor
[MRCTF2020]Xor 附件 步骤: 例行检查,32位程序,无壳 32位ida载入,首先检索程序里的字符串,根据字符串的提示,跳转到程序的关键函数 根据flag,跳转到sub_401090函数 ...
- [BUUCTF]REVERSE——[MRCTF2020]Transform
[MRCTF2020]Transform 附件 步骤: 例行检查,64位程序,无壳 64位ida载入,找到关键函数 一开始让我们输入一个长度为33位的字符串,之后使用数组dword_40F040打乱了 ...
- MRCTF2020 你传你🐎呢
MRCTF2020 你传你 .htaccess mime检测 1.先尝试上传了一个文件,发现.jpg后缀的可以上传成功,但是用蚁剑连接时返回空数据 2.重新先上传一个.htaccess文件,让需要被上 ...
- BUU XSS COURSE 1 & [CISCN2019 华东北赛区]Web2
BUU XSS COURSE 1 & [CISCN2019 华东北赛区]Web2 XSS的题目没怎么做过,比赛基本上也没有(=_=),总结下今天做的两题 都是看赵总视频现学现做的,这里附上学习 ...
随机推荐
- BUCK BOOST学习总结
首先对于我这种电源方面的小白来说 关于电源用的最多的就是线性稳压了 开关类的如 TI 的TPS系列 我是只知道应用电路而不知道具体原理的 但是长此以往也不是个办法 于是今天就带打家详细的来讲一下 ...
- Python数模笔记-PuLP库(1)线性规划入门
1.什么是线性规划 线性规划(Linear programming),在线性等式或不等式约束条件下求解线性目标函数的极值问题,常用于解决资源分配.生产调度和混合问题.例如: max fx = 2*x1 ...
- golang快速入门(四)
提示:本系列文章适合有其他语音基础并对Go有持续冲动的读者 一.golang获取HTTP请求 1.在golang标准库中提供了net包来处理网络连接,通过http.Get创建http请求并返回服务器响 ...
- Step By Step(Lua数据持久化)
Step By Step(Lua数据持久化) 1. 数据文件: 我们可以利用Lua中table的构造式来定义一种文件格式,即文件中的数据是table构造并初始化的代码,这种方式对于Lua程序而言 ...
- 深度学习LiDAR定位:L3-Net
深度学习LiDAR定位:L3-Net 摘要 本文提出L3-Net--一种新颖的基于学习的LiDAR定位系统,可实现厘米级的定位,与现有最高水平的传统定位算法相媲美.与传统定位算法不同,本文创新地实现了 ...
- 2020年Yann Lecun深度学习笔记(上)
2020年Yann Lecun深度学习笔记(上)
- 如何为嵌入式应用选择适当的SSD
如何为嵌入式应用选择适当的SSD Selecting the right SSD for evolving embedded applications 变革涉及技术的每一个要素,闪存也不例外.价格下跌 ...
- Java重载方法如何竞争
突然想起以前遇到的一道笔试题,题目大概是这样子的 // 父类 public class Father { } // 子类 public class Son extends Father { } // ...
- 单点突破:MySQL之索引
前言 开发环境:MySQL5.7.31 什么是索引 在MySQL中,索引(Index)是帮助高效获取数据的数据结构. 我们可以将数据库理解为一本书,数据库中的各个数据列(column)就是目录中的章节 ...
- pytest xfail的使用
@pytest.mark.xfail: 期望测试用例是失败的,但是不会影响测试用例的的执行; 如果测试用例执行失败的则结果是xfail(不会额外显示出错误信息); 如果测试用例执行成功的则结果是xpa ...