目录
[BJDCTF2020]JustRE
老思路,进来可以先看看string视图,找关键的字符串

发现了很有用的东西,双击看看

引用aBjdDD2069a4579后按x

看来字符串前面的两个%d分别是19999和0(学过c语言应该都见过这种形式的字符串吧,%d表示整数)
flag就是它了{1999902069a45792d233ac}
刮开有奖
这个可就难了,写了很久,同时也参考了其他大佬的wp,下面用自己的话简单阐述一下吧
先找到主要的函数吧(找到关键函数正常是依着main一步一步来的,或者可以直接锁定一些处理字符串的看起来比较有逻辑的函数也是个很不错思路)
基本确定DialogFunc是我们要审计的伪代码了

我们先看下这个函数里头引用了那些函数,先看看这个GetDlgItemTextA()吧
双击点入,按f5也没反应,猜测是接口函数了(类似于c语言的scanf)

看不太懂汇编,害
总之也是要我们输入String了,那么String应该就是我们的目标字符串了(它符合条件就是flag了)
往下审计
这里要提一嘴,用IDA转伪码时,没有数组这一概念,只有你的地址相不相邻,如,我们可以看看这道题定义变量的部分
const char *v4; // esi const char *v5; // edi int v7; // [esp+8h] [ebp-20030h] int v8; // [esp+Ch] [ebp-2002Ch] int v9; // [esp+10h] [ebp-20028h] int v10; // [esp+14h] [ebp-20024h] int v11; // [esp+18h] [ebp-20020h] int v12; // [esp+1Ch] [ebp-2001Ch] int v13; // [esp+20h] [ebp-20018h] int v14; // [esp+24h] [ebp-20014h] int v15; // [esp+28h] [ebp-20010h] int v16; // [esp+2Ch] [ebp-2000Ch] int v17; // [esp+30h] [ebp-20008h] CHAR String; // [esp+34h] [ebp-20004h] char v19; // [esp+35h] [ebp-20003h] char v20; // [esp+36h] [ebp-20002h] char v21; // [esp+37h] [ebp-20001h] char v22; // [esp+38h] [ebp-20000h] char v23; // [esp+39h] [ebp-1FFFFh] char v24; // [esp+3Ah] [ebp-1FFFEh] char v25; // [esp+3Bh] [ebp-1FFFDh] char v26; // [esp+10034h] [ebp-10004h] char v27; // [esp+10035h] [ebp-10003h] char v28; // [esp+10036h] [ebp-10002h]大伙注意看注释的部分,[esp+8h],[esp+Ch]这些的,这些都是他们的地址情况,然后再看看它们int地址的差值是4,例如v7和v8相差为(Ch-8h)=4,char地址差值是1,正好和他们数据类型所占的字节大小相等,画个图大家好理解
可见,虽然int v7,int v8虽然在以c语言的视角看来是定义不同的数据,但是它们地址是相邻的呀!因此,我们在伪代码转c语言的时候,可以把v7,v8,....v17当一个int数组(你想的话也可以是字符串)来看,同时String,v19,v20...v25当一个字符串来看
有了上面的补充,接下来我们来看一下这一部分的代码
if ( strlen(&String) == 8 )
{
v7 = 'Z';
v8 = 'J';
v9 = 'S';
v10 = 'E';
v11 = 'C';
v12 = 'a';
v13 = 'N';
v14 = 'H';
v15 = '3';
v16 = 'n';
v17 = 'g';
sub_4010F0(&v7, 0, 10);
memset(&v26, 0, 0xFFFFu);
v26 = v23;
v28 = v25;
v27 = v24;
v4 = (const char *)sub_401000(&v26, strlen(&v26));
memset(&v26, 0, 0xFFFFu);
v27 = v21;
v26 = v20;
v28 = v22;
v5 = (const char *)sub_401000(&v26, strlen(&v26));
if ( String == v7 + 34
&& v19 == v11
&& 4 * v20 - 141 == 3 * v9
&& v21 / 4 == 2 * (v14 / 9)
&& !strcmp(v4, "ak1w")
&& !strcmp(v5, "V1Ax") )
{
MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
}
}
把它弄成c语言代码让他看起来没那么难受吧,也就是把v7,v8,v9分别换成v[0],v[1],v[3]等
String,v19,v20换成了flag[0],flag[1],flag[2]等(算了写一下吧)
const char *v4; // esi
const char *v5; // edi
int v7; // v[0]
int v8; // v[1]
int v9; // v[2]
int v10; // v[3]
int v11; // v[4]
int v12; // v[5]
int v13; // v[6]
int v14; // v[7]
int v15; // v[8]
int v16; // v[9]
int v17; // v[10]
CHAR String; // flag[0]
char v19; // flag[1]
char v20; // flag[2]
char v21; // flag[3]
char v22; // flag[4]
char v23; // flag[5]
char v24; // flag[6]
char v25; // flag[7]
char v26; // v26[0]
char v27; // v26[1]
char v28; // v26[2]
下面就是我转到c语言代码了(如果有错误请师傅们谅解指正)
if (strlen(flag)==8) {
int v[] = {90,74,83,69,67,97,78,72,51,110,103};//尽量用int数组不用字符串吧,被坑了很多次了
sub_4010F0(&v7, 0, 10);
memset(v26, 0, 0xFFFFu);
v26[0] = flag[5];
v26[1] = flag[6];
v26[2] = flag[7];
char *v4 = (char*)sub_401000(v26, 3);
memset(v26, 0, 0xFFFFu);
v26[0] = flag[2];
v26[1] = flag[3];
v26[2] = flag[4];
char* v5 = (char*)sub_401000(v26, 3);
if (flag[0] == v[0] + 34
&& flag[1] == v[4]
&& 4 * flag[2] - 141 == 3 * v[2]
&& v[3] / 4 == 2 * (v[7] / 9)
&& !strcmp(v4, "ak1w")
&& !strcmp(v5, "V1Ax"))
{
MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);//输出正确吧
}
}
这下我们的重点就是审计sub_4010F0和sub_401000这两个函数了
先来看一下sub_4010F0吧

看不懂,没关系 我们也可以改呀(逆向对于将汇编伪代码改成c语言代码这项技能也有要求,以后刷题也会多多注意),但是我们先要了解一个知识点
补充知识:
大伙第一次看到*(_DWORD *)(a1+4*i)这些玩意刚开始应该有点懵,我问了下gpt这个_DWORD是int的意思,但是在代码直接把_DWORD替换成int会出现乱码,之后看了其他大佬的wp他们都提到了一个寻址公式,总结一下就是
A[i]_address = base_address + i * data_type_size
举个例子吧:
对于int a[n],我想访问下标为 i 的值,那么我们可以
a[i]=*(int *)(a+sizeof(int)*i)=*(int *)(a+4*i)
原理很简单,学过c语言的应该都会有大概了解,用一张图稍微讲解一下吧(举个例子而已,和题目无关)
接下来只要把那些寻址公式改成数组索引就行了
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<string>
using namespace std;
int sub_4010F0(int *a1, int a2, int a3)
{
int result; // eax
int i; // esi
int v5; // ecx
int v6; // edx
result = a3;
for (i = a2; i <= a3; a2 = i)
{
v5 = i;
v6 = a1[i];
if (a2 < result && i < result)
{
do
{
if (v6 > a1[result])
{
if (i >= result)
break;
++i;
v5 [a1] = a1[result];
if (i >= result)
break;
while (a1[i] <= v6)
{
if (++i >= result)
goto LABEL_13;
}
if (i >= result)
break;
v5 = i;
a1[result] = a1[i];
}
--result;
} while (i < result);
}
LABEL_13:
a1[result] = v6;
sub_4010F0(a1, a2, i - 1);
result = a3;
++i;
}
return result;
}
int main() {
int v[] = { 90,74,83,69,67,97,78,72,51,110,103 };
sub_4010F0(v, 0, 10);
for (int i = 0; i <= 10; i++) {
printf("%c", v[i]);
}
return 0;
}
结果是这个

进入sub_401000函数

好像按前面这个方法改动的话比较困难,先把_BYTE这个玩意改成char试试吧(问gpt的,这玩意是汇编特征) 然后再查看byte_407830这个字符串是啥

写成c语言代码就是这样了
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<string>
using namespace std;
char* __cdecl sub_401000(char* a1, int a2)
{
int v2; // eax
int v3; // esi
size_t v4; // ebx
char* v5; // eax
char* v6; // edi
int v7; // eax
char* v8; // ebx
int v9; // edi
signed int v10; // edx
int v11; // edi
signed int v12; // eax
signed int v13; // esi
char* result; // eax
char* v15; // [esp+Ch] [ebp-10h]
char* v16; // [esp+10h] [ebp-Ch]
int v17; // [esp+14h] [ebp-8h]
int v18; // [esp+18h] [ebp-4h]
v2 = a2 / 3;
v3 = 0;
if (a2 % 3 > 0)
++v2;
v4 = 4 * v2 + 1;
v5 = (char*)malloc(v4);
v6 = v5;
v15 = v5;
if (!v5)
exit(0);
memset(v5, 0, v4);
v7 = a2;
v8 = v6;
v16 = v6;
if (a2 > 0)
{
while (1)
{
v9 = 0;
v10 = 0;
v18 = 0;
do
{
if (v3 >= v7)
break;
++v10;
v9 = *(unsigned __int8*)(v3++ + a1) | (v9 << 8);
} while (v10 < 3);
v11 = v9 << 8 * (3 - v10);
v12 = 0;
v17 = v3;
v13 = 18;
do
{
if (v10 >= v12)
{
*((char*)&v18 + v12) = (v11 >> v13) & 0x3F;
v8 = v16;
}
else
{
*((char*)&v18 + v12) = 64;
}
char byte_407830[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
*v8++ = byte_407830[*((char*)&v18 + v12)];
v13 -= 6;
++v12;
v16 = v8;
} while (v13 > -6);
v3 = v17;
if (v17 >= a2)
break;
v7 = a2;
}
v6 = v15;
}
result = v6;
*v8 = 0;
return result;
}
int main() {
char a[] = "aaaa";
char *b= sub_401000(a, strlen(a));
printf("%s", b);
return 0;
}
随便把一个字符串"aaa"扔进去吧 ,看看结果

这不是base64加密码?(其实看到"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="这个字符串就应该意识到了,但是我菜)
因此伪代码里头的v4,v5都是base64加密后的结果
对他们解密


这样我们的问题全部解决了, 写程序得到flag吧
int main() {
char flag[8] = "";
char v4[] = "jMp";
char v5[] = "WP1";
char v[] = "3CEHJNSZagn";
flag[0] = v[0] + 34;
flag[1] = v[4];
flag[2] = (3 * v[2] + 141) / 4;
flag[3] = 4 * 2 * (v[7] / 9);
flag[4] = v5[2];
flag[5] = v4[0];
flag[6] = v4[1];
flag[7] = v4[2];
for (int i = 0; i < 8; i++) {
printf("%c", flag[i]);
}
return 0;
}
执行完就是flag了

[ACTF新生赛2020]easyre
用ida打开,函数都挺抽象的,看不出逻辑。。。
用exeinforPE一看应该有壳

直接用upx脱壳吧

脱壳后再放入ida
看伪码

这道题有很多坑!首先_data_start_字符串点进去不全,要按shift+e查看完整数组才能看全(以后查看汇编层的字符串一定要注意)

然后伪代码转c语言的时候尽量转成int数组,如果直接用字符串的话会出现很多错误(反正我是这样的)可以先把字符串转成int数组
稍微看一下我们的flag就是要求这段以v5开头地址串(int和char混合,抽象)

依据这个循环,直接写出程序

int main() {
int s[] = { 126,125, 124, 123, 122, 121, 120, 119, 118, 117, 116,
115, 114, 113, 112, 111, 110, 109, 108, 107, 106,
105, 104, 103, 102, 101, 100, 99, 98, 97, 96,
95, 94, 93, 92, 91, 90, 89, 88, 87, 86,
85, 84, 83, 82, 81, 80, 79, 78, 77, 76,
75, 74, 73, 72, 71, 70, 69, 68, 67, 66,
65, 64, 63, 62, 61, 60, 59, 58, 57, 56,
55, 54, 53, 52, 51, 50, 49, 48, 47, 46,
45, 44, 43, 42, 41, 40, 39, 38, 37, 36,
35, 32, 33, 34 };
char v4[] = { 42, 70, 39, 34, 78, 44, 34, 40, 73, 63, 43, 64 };
char flag[] = { '0' };
for (int i = 0; i <= 11; i++) {
for (char a = '!'; a <= 'z'; a++) {
if (v4[i] == s[a - 1]) {
printf("%c", a);
}
}
}
return 0;
}
得到flag

简单注册器
app逆向,但是我们这次用到工具是jadx-gui可以直接看到java源代码,拖进去找到关键的地方

可见这个bbb字符串就是我们的flag了,直接执行这个java程序
public class Main {
public static void main(String[] args) {
char[] x = "dd2940c04462b4dd7c450528835cca15".toCharArray();
x[2] = (char) ((x[2] + x[3]) - 50);
x[4] = (char) ((x[2] + x[5]) - 48);
x[30] = (char) ((x[31] + x[9]) - 48);
x[14] = (char) ((x[27] + x[28]) - 97);
for (int i = 0; i < 16; i++) {
char a = x[31 - i];
x[31 - i] = x[i];
x[i] = a;
}
String bbb = String.valueOf(x);
System.out.println(bbb);
}
}
执行完就是flag了



&spm=1001.2101.3001.5002&articleId=142964823&d=1&t=3&u=3b4190a62f154e0eba2c667f2cc5f255)
1273

被折叠的 条评论
为什么被折叠?



