[HUBUCTF 2022 新生赛]simple_RE

查壳,64位

找main函数,F5查看伪代码,简单分析一下

int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [rsp+24h] [rbp-44h] BYREF
void *Buf1; // [rsp+28h] [rbp-40h] BYREF
char v6[56]; // [rsp+30h] [rbp-38h] BYREF sub_401770(argc, argv, envp);
printf("please input the flag:");
scanf("%s", v6); // v6是flag
Buf1 = 0i64; // 初始化Buf1
sub_401570(v6, &Buf1, &v4); // v6进行base64编码,但是不是根据A-Z,...,而是根据这串字符编码qvEJAfHmUYjBac+u8Ph5n9Od17FrICL/X0gVtM4Qk6T2z3wNSsyoebilxWKGZpRD
if ( !memcmp(Buf1, a5mc58bphliax7j, v4) ) // 对这串字符串"5Mc58bPHLiAx7J8ocJIlaVUxaJvMcoYMaoPMaOfg15c475tscHfM/8=="进行微改变的base64解码,即得flag
printf("\nsuccess!");
else
printf("\nfailed!");
if ( Buf1 )
free(Buf1);
return 0;
}

v6是flag,经过sub_401570函数加密,得到a5mc58bphliax7j对应的加密后的值,即加密后的flag值

这里的重点就是sub_401570函数,我们需要了解经过怎么样的加密,接下来我们点进去看看

sub_401570函数

__int64 __fastcall sub_401570(const char *a1, _QWORD *a2, int *a3)
{
int v6; // r15d
int v7; // r12d
int v8; // r13d
__int64 v9; // r14
_BYTE *v10; // rax
_BYTE *v11; // r9
__int64 v12; // r8
char v13; // cl
char v14; // r11
char v15; // r10
__int64 result; // rax v6 = strlen(a1);
v7 = v6 % 3;
if ( v6 % 3 )
{
v8 = 4 * (v6 / 3) + 4;
v9 = v8;
v10 = malloc(v8 + 1i64);
v10[v8] = 0;
if ( v6 <= 0 )
goto LABEL_5;
}
else
{
v8 = 4 * (v6 / 3);
v9 = v8;
v10 = malloc(v8 + 1i64);
v10[v8] = 0;
if ( v6 <= 0 )
goto LABEL_8;
}
v11 = v10;
v12 = 0i64;
do
{
v11 += 4;
v13 = a1[v12];
*(v11 - 4) = aQvejafhmuyjbac[v13 >> 2];
v14 = a1[v12 + 1];
*(v11 - 3) = aQvejafhmuyjbac[(v14 >> 4) | (16 * v13) & 0x30];
v15 = a1[v12 + 2];
v12 += 3i64;
*(v11 - 2) = aQvejafhmuyjbac[(v15 >> 6) | (4 * v14) & 0x3C];
*(v11 - 1) = aQvejafhmuyjbac[v15 & 0x3F];
}
while ( v6 > (int)v12 );
LABEL_5:
if ( v7 == 1 )
{
v10[v9 - 2] = 61;
v10[v9 - 1] = 61;
}
else if ( v7 == 2 )
{
v10[v9 - 1] = 61;
}
LABEL_8:
*a2 = v10;
result = 0i64;
*a3 = v8;
return result;
}

看不懂不要紧,为了这个,我专门用一天时间消化base64编码与解码的原理,链接如下:base64详解 - Zer0o - 博客园 (cnblogs.com)

看完,就能对base64原理了解的八九不离十了

这段代码一看移位运算,或运算,与运算,与base64编码一样,只不过base64是根据ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/编码,而这里修改为aQvejafhmuyjbac对应的字符串

双击进入,知道这个base64是根据这串字符串编码的qvEJAfHmUYjBac+u8Ph5n9Od17FrICL/X0gVtM4Qk6T2z3wNSsyoebilxWKGZpRD,而不是ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

知道原理了,返回main函数

简单捋一下,就是将flag进行变异的base64编码,编码结果为a5mc58bphliax7j对应的数据,即5Mc58bPHLiAx7J8ocJIlaVUxaJvMcoYMaoPMaOfg15c475tscHfM/8==

写出源码

#include <stdio.h>
#include <string.h>
#include <stdlib.h> char base64CharsArr[] = "qvEJAfHmUYjBac+u8Ph5n9Od17FrICL/X0gVtM4Qk6T2z3wNSsyoebilxWKGZpRD"; void base64decode(char str[]) {
int length = strlen(str);
int padding = 0; // 计算填充字符数量
if (str[length - 1] == '=') {
padding++;
if (str[length - 2] == '=')
padding++;
} // 计算解码后的字符数量
int decodedLength = (length * 3) / 4 - padding; // 分配存储解码结果的内存
char* decodedStr = (char*)malloc(decodedLength + 1); int outIndex = 0;
for (int i = 0; i < length; i += 4) {
char char1 = -1, char2 = -1, char3 = -1, char4 = -1; // 查找每个字符在Base64字符集中的索引
for (int j = 0; j < 64; j++) {
if (base64CharsArr[j] == str[i]) {
char1 = j;
break;
}
} for (int j = 0; j < 64; j++) {
if (base64CharsArr[j] == str[i + 1]) {
char2 = j;
break;
}
} for (int j = 0; j < 64; j++) {
if (base64CharsArr[j] == str[i + 2]) {
char3 = j;
break;
}
} for (int j = 0; j < 64; j++) {
if (base64CharsArr[j] == str[i + 3]) {
char4 = j;
break;
}
} // 解码并存储结果
decodedStr[outIndex++] = (char1 << 2) | ((char2 & 0x30) >> 4);
if (char3 != -1)
decodedStr[outIndex++] = ((char2 & 0xf) << 4) | ((char3 & 0x3c) >> 2);
if (char4 != -1)
decodedStr[outIndex++] = ((char3 & 0x3) << 6) | char4;
} // 添加字符串结束符
decodedStr[decodedLength] = '\0'; printf("Decoded string: %s\n", decodedStr); // 释放内存
free(decodedStr);
} int main() {
char str[100]="5Mc58bPHLiAx7J8ocJIlaVUxaJvMcoYMaoPMaOfg15c475tscHfM/8=="; // Example base64 encoded string
base64decode(str);
return 0;
}

flag:NSSCTF{a8d4347722800e72e34e1aba3fe914ae}

[HUBUCTF 2022 新生赛]simple_RE的更多相关文章

  1. SCNU ACM 2016新生赛初赛 解题报告

    新生初赛题目.解题思路.参考代码一览 1001. 无聊的日常 Problem Description 两位小朋友小A和小B无聊时玩了个游戏,在限定时间内说出一排数字,那边说出的数大就赢,你的工作是帮他 ...

  2. SCNU 2015ACM新生赛决赛【F. Oyk闯机关】解题报告

            题目大意:一个$N$$\times$$N$的阵列,每个格子有$X_{ij}$个调和之音,若每次只能选择走右边或下边,从左上角出发走到右下角,问最多能收集到多少个调和之音?       ...

  3. Codeforces 801 A.Vicious Keyboard & Jxnu Group Programming Ladder Tournament 2017江西师大新生赛 L1-2.叶神的字符串

    A. Vicious Keyboard time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  4. [ACTF2020 新生赛]BackupFile && [ACTF2020 新生赛]Upload &&[GYCTF2020]Blacklist

    [ACTF2020 新生赛]BackupFile 尝试找到源代码,加上题目是备份文件,猜测备份文件里面有网站的源代码,御剑扫描一下,就扫到index.php 访问index.php.bak 下载源代码 ...

  5. [BUUCTF]REVERSE——[ACTF新生赛2020]Oruga

    [ACTF新生赛2020]Oruga 附件 步骤: 例行检查,64位程序,无壳 64位ida载入,检索字符串,根据提示来到关键函数 14行~18行就是让字符串的前5位是 actf{ ,sub_78A( ...

  6. [BUUCTF]REVERSE——[ACTF新生赛2020]usualCrypt

    [ACTF新生赛2020]usualCrypt 附件 步骤: 例行检查,无壳,32位程序 32位ida载入,直接看main函数 逻辑很简单,一开始让我们输入一个字符串,然后该字符串经过sub_4010 ...

  7. [BUUCTF]REVERSE——[ACTF新生赛2020]rome

    [ACTF新生赛2020]rome 附件 步骤 无壳,32位程序 32位ida载入,根据提示字符串"You are correct!",找到关键函数func v15 = 'Q'; ...

  8. [BUUCTF]REVERSE——[ACTF新生赛2020]easyre

    [ACTF新生赛2020]easyre 附件 步骤 查壳,32位程序,upx壳儿 脱完壳儿,扔进ida 分析 一开始给我们定义了一个数组, v4=[42,70,39,34,78,44,34,40,73 ...

  9. GDOU-CTF-2023新生赛Pwn题解与反思

    第一次参加CTF新生赛总结与反思 因为昨天学校那边要进行天梯模拟赛,所以被拉过去了.16点30分结束,就跑回来宿舍开始写.第一题和第二题一下子getshell,不用30分钟,可能我没想那么多,对比网上 ...

  10. SCNU ACM 2016新生赛决赛 解题报告

    新生初赛题目.解题思路.参考代码一览 A. 拒绝虐狗 Problem Description CZJ 去排队打饭的时候看到前面有几对情侣秀恩爱,作为单身狗的 CZJ 表示很难受. 现在给出一个字符串代 ...

随机推荐

  1. 一文吃透Elasticsearch

    本文已经收录到Github仓库,该仓库包含计算机基础.Java基础.多线程.JVM.数据库.Redis.Spring.Mybatis.SpringMVC.SpringBoot.分布式.微服务.设计模式 ...

  2. 用PHPstudy nginx 配置tp6 隐藏访问链接中的index.php

    在server 里面加上如下这个判断就好了 if (!-e $request_filename){ rewrite ^(.*)$ /index.php?s=$1 last; break; 配置在对应网 ...

  3. es6的Symbol数据类型

    ES6引入了一种新的原始数据类型Symbol,表示独一无二的值.它是JavaScript语言的第七种数据类型,前六种是:Undefined.Null.布尔值(Boolean).字符串(String). ...

  4. 【Linux】Linux 基础入门

    Linux 发行版(发行版之间的联系与区别) 红帽公司开发的RedHat Enterprise Linux,它是全世界内使用最广泛的Linux系统,具有极强的性能与稳定性,并且在全球范围内拥有完善的技 ...

  5. node可以用nvm快速切换版本,golang如何快速切换版本?用gvm就行。

    使用 gvm 可以带来以下好处: 快速切换 Golang 版本,方便进行版本测试和开发: 可以在多个项目中同时使用不同版本的 Golang 包和工具,避免冲突: 可以通过 gvm 管理不同版本的 Go ...

  6. 2022-10-15:给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。 你可以按 任意顺序 返回答案。 要求时间复杂度O(N)。 输入: nums = [1,1,1

    2022-10-15:给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素. 你可以按 任意顺序 返回答案. 要求时间复杂度O(N). 输入: nums = [1,1,1 ...

  7. openstack部署2

    检查服务,查看dashboard页面有哪些功能 检查服务状态 检查计算节点,控制节点服务是up状态 检查网络节点是True的状态.这里的每个计算节点,都是一个neutron的客户端. 查看dashbo ...

  8. Python对word文档重排版

    介绍 舍友从网上下载的word题库文档很乱,手动改了大半天才改了一点,想起python是大名鼎鼎的自动化脚本,于是乎开始了python对word的一顿瞎操作. 分析需求 对文档中的内容进行分析,只留下 ...

  9. 洛谷P3368 【模板】树状数组 2-(区间修改,单点查询)

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 将某区间每一个数加上 x: 求出某一个数的值. 输入格式 第一行包含两个整数 N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含 N  ...

  10. 【实战分享】使用 Go 重构流式日志网关

    项目背景 分享之前,先来简单介绍下该项目在流式日志处理链路中所处的位置. 流式日志网关的主要功能是提供 HTTP 接口,接收 CDN 边缘节点上报的各类日志(访问日志/报错日志/计费日志等),将日志作 ...