上次没写出,这次认真分析了一下,发现自己的调试水平也有了上涨,也看了一些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的更多相关文章

  1. 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 ...

  2. Buu刷题

    前言 希望自己能够更加的努力,希望通过多刷大赛题来提高自己的知识面.(ง •_•)ง easy_tornado 进入题目 看到render就感觉可能是模板注入的东西 hints.txt给出提示,可以看 ...

  3. BUU刷题01

    [安洵杯 2019]easy_serialize_php 直接给了源代码 <?php $function = @$_GET['f']; function filter($img){ $filte ...

  4. buu学习记录(上)

    前言:菜鸡误入buu,差点被打吐.不过学到了好多东西. 题目名称: (1)随便注 (2)高明的黑客 (3)CheckIn (4)Hack World (5)SSRF Me (6)piapiapia ( ...

  5. [BUUCTF]REVERSE——[MRCTF2020]hello_world_go

    [MRCTF2020]hello_world_go 附件 步骤: 例行检查,64位程序,无壳 64位ida载入,检索程序里的字符串,有很多,直接检索flag 一个一个点过去,找到了flag 按a,提取 ...

  6. [BUUCTF]REVERSE——[MRCTF2020]Xor

    [MRCTF2020]Xor 附件 步骤: 例行检查,32位程序,无壳 32位ida载入,首先检索程序里的字符串,根据字符串的提示,跳转到程序的关键函数 根据flag,跳转到sub_401090函数 ...

  7. [BUUCTF]REVERSE——[MRCTF2020]Transform

    [MRCTF2020]Transform 附件 步骤: 例行检查,64位程序,无壳 64位ida载入,找到关键函数 一开始让我们输入一个长度为33位的字符串,之后使用数组dword_40F040打乱了 ...

  8. MRCTF2020 你传你🐎呢

    MRCTF2020 你传你 .htaccess mime检测 1.先尝试上传了一个文件,发现.jpg后缀的可以上传成功,但是用蚁剑连接时返回空数据 2.重新先上传一个.htaccess文件,让需要被上 ...

  9. BUU XSS COURSE 1 & [CISCN2019 华东北赛区]Web2

    BUU XSS COURSE 1 & [CISCN2019 华东北赛区]Web2 XSS的题目没怎么做过,比赛基本上也没有(=_=),总结下今天做的两题 都是看赵总视频现学现做的,这里附上学习 ...

随机推荐

  1. 浅谈:@RequestBody,@ResponseBody 和 @RequestParam

    1. @RequestBody @RequestBody:主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据) GET方式无请求体,所以使用@RequestBody接收数据时,前端不 ...

  2. Git指令大全

    仓库 # 在当前目录新建一个Git代码库 $ git init # 下载一个项目和它的整个代码历史 $ git clone [url] 配置 # 显示当前的Git配置 $ git config --l ...

  3. 微信小程序从开发到上线流程

    一.微信小程序从开发到上线流程 注册小程序 1.登录微信公众平台 https://mp.weixin.qq.com 2.在微信公众平台>立即注册>小程序中注册微信小程序 3.在邮箱中激活并 ...

  4. 关于Linux的一些基础命令

    今天学习scala语言,在linux系统上运行,发现对Linux的命令不太熟悉,为了熟悉掌握,也便于查询,这些命令主要是为了收藏备用,,希望能帮助到大家 linux20个常用命令是: 1.显示日期的指 ...

  5. Jmeter - 把提取的响应结果设置成全局变量

    1. 用正则表达式从响应结果中提取需要的字符 2.添加BeanShell 后置处理程序,${__setProperty(setcookies,${cookies},)} 用函数定义其为全局变量 3.调 ...

  6. (转)修改python默认排序方式

    在Java中,自定义类可以通过继承comparable接口,重写compareTo方法来使用内置sort()函数来对自定义对象排序,我就在想Python中有没有类似的操作. 首先随便写个自定义类,比如 ...

  7. TVM代码生成codegen

    TVM代码生成codegen 硬件后端提供程序(例如Intel,NVIDIA,ARM等),提供诸如cuBLAS或cuDNN之类的内核库以及许多常用的深度学习内核,或者提供框架例,如带有图形引擎的DNN ...

  8. 机器学习PAI

    机器学习PAI 机器学习PAI(Platform of Artificial Intelligence)是阿里云人工智能平台,提供一站式的机器学习解决方案.本文介绍什么是机器学习PAI. 什么是机器学 ...

  9. 学习响应式编程 Reactor (2) - 初识 reactor

    Reactor Reactor 是用于 Java 的异步非阻塞响应式编程框架,同时具备背压控制的能力.它与 Java 8 函数式 Api 直接集成,比如 分为CompletableFuture.Str ...

  10. 框架篇:分布式全局唯一ID

    前言 每一次HTTP请求,数据库的事务的执行,我们追踪代码执行的过程中,需要一个唯一值和这些业务操作相关联,对于单机的系统,可以用数据库的自增ID或者时间戳加一个在本机递增值,即可实现唯一值.但在分布 ...