admin 管理员组文章数量: 887019
BUUCTF
BUUCTF-Re
- BUUCTF-逆向
- 1.easyre
- 2.reverse1
- 3.reverse2
- 4.内涵的软件
- 5.新年快乐
- 6.helloword
- 7.xor
- 8.reverse3
- 9.不一样的flag
- 10.SimpleRev
- 11.Java逆向解密
- 12.刮开有奖
- 13.rsa
- 14.findit
- 15.简单注册器
- 16.[BJDCTF2020]JustRE
- 17.[GWCTF 2019]pyre
- 18.[GXYCTF2019]luck_guy
- 19.[ACTF新生赛2020]easyre
- 20.CrackRTF
- 21.[ACTF新生赛2020]rome
- 22.[FlareOn4]login
- 23.[2019红帽杯]easyRE
- 24.[GUET-CTF2019]re
- 25.[WUSTCTF2020]level1
BUUCTF-逆向
1.easyre
先用虚拟机看看是多少位的文件;
拖进IDA看看,一下子就出来了;
2.reverse1
先用虚拟机看看是多少位的文件;
打开IDA,查找字符串;
点击View->Open subviews->Strings
然后观察伪代码
所有的 ’ o ’全都变成 ’ 0 ‘ ;
flag{hell0_w0rld}
3.reverse2
一样的看看文件是多少位的;
在IDA中F5反汇编,得到伪代码;
大概意思是如果字符串里面有 ’ i ’ 或者 ‘ r ',则变更成 ’ 1 ‘ ;
在IDA中,找字符串,找到了flag;
所以根据代码提示
最终flag为
flag{hack1ng_fo1_fun}
4.内涵的软件
查看位数
工具查看一下,无壳;
IDA32位打开就有,简单的考验眼力;
flag{49d3c93df25caad81232130f3d2ebfad}
5.新年快乐
查壳一查,发现有壳;
拖到虚拟机里面去脱壳;
然后file一下,看出是32位的,再拖到IDA里面去看看
主函数很简单,就不用细说了,就是一个比较,
得到flag为:
flag{HappyNewYear!}
6.helloword
是一个apk文件,android逆向;
用APKIDE打开附件
搜索flag
flag{7631a988259a00816deda84afb29430a}
7.xor
异或运算,没有加壳;
拖进IDA看一下;
逻辑很简单,就是把下一个和之前的一个异或,然后保存。
这里的数据比较奇怪了,既有数据,又有字符。所以不要单纯的复制下来,要转换为ascii码,然后进行异或,最后贴上脚本。
a=[0x66,0x0A,0x6b,0x0C,0x77,0x26,0x4f,0x2e,0x40,0x11,0x78,0x0D,0x5a,0x3b,0x55,0x11,0x70,0x19,0x46,0x1F,0x76,0x22,0x4d,0x23,0x44,0x0E,0x67,0x06,0x68,0x0F,0x47,0x32,0x4f]
s=' '
s+='f'
for i in range(1,len(a)):s+=chr(a[i]^a[i-1])
print(s)
得出来flag;
flag{QianQiuWanDai_YiTongJiangHu}
8.reverse3
首先打开IDA返汇编得到伪代码;
点击Str2,看一下其中的内容;
然后点击sub_4110BE,看一下加密运算;
发现使用了这个进行数组变换,跟进发现就是之前的base64。
首先for循环将Dest每一位都加了j,所以写脚本还原v1,然后进行base64解码
import base64str='e3nifIH9b_C@n@dH'
flag=' '
for i in range(len(str)):flag+=chr(ord(str[i])-i)
flag=base64.b64decode(flag)
print(flag)
得到flag
flag{i_l0ve_you}
9.不一样的flag
使用IDA一打开就看到一个可以数据;
以为是十六进制编码啥的,发现都不对;
发现反汇编出来的伪代码也有点奇奇怪怪的;
可以发现有上下左右四个方向,并且碰到1退出,碰到#输出flag,应该是一个迷宫,再查看01串长度正好25;
得到222441144222
flag{222441144222}
10.SimpleRev
首先就是一个普普通通的64位文件,简单题就不看有没有加壳了,大概率是没有的。
老样子拖进IDA看看情况。
这个伪代码一看就不简单。
关键就在于Dercy()这个函数,点进去看一下。
v12 = *MK_FP(__FS__, 40LL);*(_QWORD *)src = 'SLCDN'; //NDCLSv7 = 0LL;v8 = 0;v9 = 'wodah'; //hadowv10 = 0LL;v11 = 0;text = join(key3, (const char *)&v9); strcpy(key, key1);strcat(key, src);v2 = 0;v3 = 0;getchar();v5 = strlen(key);for ( i = 0; i < v5; ++i ){if ( key[v3 % v5] > '@' && key[v3 % v5] <= 'Z' )key[i] = key[v3 % v5] + 32;++v3;}printf("Please input your flag:", src);while ( 1 ){v1 = getchar();if ( v1 == '\n' )break;if ( v1 == ' ' ){++v2;}else{if ( v1 <= 96 || v1 > 122 ){if ( v1 > '@' && v1 <= 'Z' )str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;}else{str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;}if ( !(v3 % v5) )putchar(32);++v2;}}if ( !strcmp(text, str2) )puts("Congratulation!\n");elseputs("Try again!\n");return *MK_FP(__FS__, 40LL) ^ v12;
}
将src和v9的值换成十六进制,可以到这两个是大端序,但是数据在内存中都是小端序,所以我们要将其转一下,一般在CPU,x86都是小端序,但是IDA将其转换为大端序。(具体如何判断我也不是很清楚,查了很多也没有一个所以然,大家就先这样记忆吧)
src = NDCLS, v9 = hadow;
join连接key3和v9,key3点进去得到kills,所以text = killshadow。
strcpy(key, key1); //复制函数,将key1的字符串复制给key。
key1点进去得到ADSFK。
strcat函数,是将key 和 src 拼接在一起的函数, 所以key = ADSFKNDCLS。
这个key[v3%v5]是大写字母,则把它变为小写字母。大小写字母的ASCII码,相差32。
看到最下面的if语句,如果!strcmp(text ,str2),则正确,strcmp函数,是比较函数,如果两个字符串相同,则等于0,所以text = str2才成功。
而得到str2的关键就是:
str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97
接下来,写脚本。
lt='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
key=list('ADSFKNDCLS'.lower())
klens=len(key)text='killshadow'
flag=''
for i in range(len(text)):str2=text[i]for c in lt:if str2== chr((ord(c) - 39 - ord(key[i % klens]) + 97) % 26 + 97):flag+=c
print('flag{'+flag+'}')
lt可以试试大写也可以试试小写,这里我个人不确定是大写还是小写,不过大写答案正确
flag{KLDQCUDFZO}
11.Java逆向解密
文件下载完成后打开是.class文件。
.class文件是.java文件编译后生成的字节码文件,我们使用一般的文本编辑工具打开的话,里面的内容是乱码。 使用专业的集成开发工具(IDE)可以打开.class文件,如eclipse,idea等。
下载了打开反汇编Java的工具
逻辑清晰简单,就是我们输入一个字符串
然后经过一个for循环进行异或
然后将得到的新字符串与KEY进行比较,看看是否相等。
解码的python脚本如下
str = [180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65 ]flag=' 'for i in range(len(str)):flag+=chr(str[i]-ord('@')^0x20)
print(flag)
得到flag为
flag{ This_is_the_flag_!}
12.刮开有奖
首先还是例行检查,看看有没有壳。
正常的文件,没有加壳。
然后我试了试x64dbg,不过并没有什么用处。
用IDA试了试,看到了DialogFunc函数,反汇编得到伪代码。
BOOL __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{const char *v4; // esi@5const char *v5; // edi@5BOOL result; // eax@14int v7; // [sp+8h] [bp-20030h]@5int v8; // [sp+Ch] [bp-2002Ch]@5int v9; // [sp+10h] [bp-20028h]@5int v10; // [sp+14h] [bp-20024h]@5int v11; // [sp+18h] [bp-20020h]@5int v12; // [sp+1Ch] [bp-2001Ch]@5int v13; // [sp+20h] [bp-20018h]@5int v14; // [sp+24h] [bp-20014h]@5int v15; // [sp+28h] [bp-20010h]@5int v16; // [sp+2Ch] [bp-2000Ch]@5int v17; // [sp+30h] [bp-20008h]@5CHAR String; // [sp+34h] [bp-20004h]@4char v19; // [sp+35h] [bp-20003h]@6char v20; // [sp+36h] [bp-20002h]@5char v21; // [sp+37h] [bp-20001h]@5char v22; // [sp+38h] [bp-20000h]@5char v23; // [sp+39h] [bp-1FFFFh]@5char v24; // [sp+3Ah] [bp-1FFFEh]@5char v25; // [sp+3Bh] [bp-1FFFDh]@5char v26; // [sp+10034h] [bp-10004h]@5char v27; // [sp+10035h] [bp-10003h]@5char v28; // [sp+10036h] [bp-10002h]@5if ( a2 == 272 ){result = 1;}else{if ( a2 != 273 )return 0;if ( (_WORD)a3 == 1001 ){memset(&String, 0, 0xFFFFu);GetDlgItemTextA(hDlg, 1000, &String, 0xFFFF);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((int)&v7, 0, 10);memset(&v26, 0, 65535u);v26 = v23;v28 = v25;v27 = v24;v4 = (const char *)sub_401000((int)&v26, strlen(&v26));memset(&v26, 0, 0xFFFFu);v27 = v21;v26 = v20;v28 = v22;v5 = (const char *)sub_401000((int)&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);}return 0;}if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 )return 0;EndDialog(hDlg, (unsigned __int16)a3);result = 1;}return result;
}
大概可以看出我们的flag是8位长度的字符串。
看伪代码分析太麻烦了,所以转成C语言代码运行一下。记得把*(_DWORD*) 删掉,因为这是汇编的表示,然后将各种基址+偏移的表示也换成数组的寻址,如下
#include <stdio.h>
#include <string.h>int sub_4010F0(char*a1,int a2,int a3)
{int result;int i;int v5;int v6;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;a1[v5]=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(void)
{char str[]="ZJSECaNH3ng";sub_4010F0(str,0,10);printf("%s",str);return 0;
}
得到结果为3CEHJNSZagn
分析代码,转到汇编处。
看加粗加红处(下面是对应字符串的信息)
我们可以知道,v6使用sub_4010F0函数后的字符串的6,7,8位,调用sub_401000函数,v7使用sub_4010F0函数后的字符串的3,4,5位,调用sub_401000函数。(这一步我自己其实一直不能理解。)
然后进入sub_401000,观察里面的加密方式。
void *__cdecl sub_401000(int a1, signed int a2)
{int v2; // eax@1signed int v3; // esi@1size_t v4; // ebx@3void *v5; // eax@3void *v6; // edi@3signed int v7; // eax@5void *v8; // ebx@5int v9; // edi@8signed int v10; // edx@8signed int v11; // edi@11signed int v12; // eax@11signed int v13; // esi@11void *result; // eax@18void *v15; // [sp+Ch] [bp-10h]@3void *v16; // [sp+10h] [bp-Ch]@5signed int v17; // [sp+14h] [bp-8h]@11int v18; // [sp+18h] [bp-4h]@8v2 = a2 / 3;v3 = 0;if ( a2 % 3 > 0 )++v2;v4 = 4 * v2 + 1;v5 = 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 = *(_BYTE *)(v3++ + a1) | (v9 << 8);}while ( v10 < 3 );v11 = v9 << 8 * (3 - v10);v12 = 0;v17 = v3;v13 = 18;do{if ( v10 >= v12 ){*((_BYTE *)&v18 + v12) = (v11 >> v13) & 0x3F;v8 = v16;}else{*((_BYTE *)&v18 + v12) = 64;}*(_BYTE *)v8 = byte_407830[*((_BYTE *)&v18 + v12)];v8 = (char *)v8 + 1;v13 -= 6;++v12;v16 = v8;}while ( v13 > -6 );v3 = v17;if ( v17 >= a2 )break;v7 = a2;}v6 = v15;}result = v6;*(_BYTE *)v8 = 0;return result;
}
又是一个很复杂的代码,然后我们看到函数byte_407830,点进去看到
一看也知道是base64加密。
if ( String == v9 + 34 // sub_4010F0函数后的第一位等于51+34=85-->'U'&& v21 == v13 // 第2位,等于v13,即sub_4010F0函数返回值的第5位值-->'J'&& 4 * v22 - 141 == 3 * v11&& v23 / 4 == 2 * (v16 / 9)&& !strcmp(v6, "ak1w") // 第6,7,8行代码base64之后,需要等于"ak1w"&& !strcmp( // 第3,4,5行代码,加密之后等于V1Axv7,"V1Ax") ){MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);}
最后得到flag为
flag{UJWP1jMp}
13.rsa
首先看到这道题目的时候真的是一头雾水,不知道给的文件是用来干什么的;
然后就去搜索enc文件,想着可以把它转换成代码,然后去分析代码,果然这条路没有走通,然后就在网上看到别人介绍RsaCtfTool这个工具,下载了好久才下载完成;
看这篇文章,来下载RsaCtfTool;
安装RsaCtfTool
然后把文件复制到Kali中,使用命令
python3 RsaCtfTool.py --publickey pub.key --uncipherfile flag.enc
得到flag
所以flag为
flag{decrypt_256}
14.findit
文件下载好了,.apk文件,安卓逆向。
用apk改之理看一看
找到主函数。
打开后看到一串十六进制数。
转换成字符的形式。
str=[0x70,0x76,0x6B,0x71,0x7b,0x6d,0x31,0x36,0x34,0x36,0x37,0x35,0x32,0x36,0x32,0x30,0x33,0x33,0x6c,
0x34,0x6d,0x34,0x39,0x6c,0x6e,0x70,0x37,0x70,0x39,0x6d,0x6e,0x6b,0x32,0x38,0x6b,0x37,0x35,0x7d]flag=''
for i in range(0,len(str)):flag+=chr(str[i])
print(flag)
得到一串字符
pvkq{m164675262033l4m49lnp7p9mnk28k75}
以为这就是flag,提交后发现不对,仔细观察后感觉像是凯撒密码
解密一下得到
flag{c164675262033b4c49bdf7f9cda28a75}
15.简单注册器
文件下载好后是一个.apk文件,安卓逆向。
用Jadx-gui反编译,得到主要代码。
然后写脚本把flag跑出来
flagtrue = "dd2940c04462b4dd7c450528835cca15"
x = [i for i in flagtrue]
x[2] = chr(ord(x[2]) + ord(x[3]) - 0x32)
x[4] = chr(ord(x[2]) + ord(x[5]) - 0x30)
x[0x1e] = chr(ord(x[0x1f]) + ord(x[0x9]) - 0x30)
x[0xe] = chr(ord(x[0x1b]) + ord(x[0x1c]) - 0x61)for i in range(16):x[i],x[31-i] = x[31-i],x[i]print ("flag{"+ ''.join(x) + "}")
这是别人写的脚本,python没学好,我自己手算的,这么简单都不会,还不赶紧学python。
得到flag为:
flag{59acc538825054c7de4b26440c0999dd}
16.[BJDCTF2020]JustRE
还是先检查一下有没有壳
没有加壳。
拖到IDA里面看一看。
找到一个比较关键的字符
找到关键函数,反编译一下
输出了aBjdDD2069a4579,19999,0,aBjdDD2069a4579是BJD{%d%d2069a45792d233ac},19999和0填入到里面的%d位置,得到flag
flag{1999902069a45792d233ac}
17.[GWCTF 2019]pyre
看到名字的时候就猜到肯定和python有关。
下载文件,果不其然.pyc文件(python代码转换为字节码后的文件)
用python反编译工具:python反编译
打开后得到
轻轻松松反编译出来
结果我自己数学不好,python写的又烂,还是看了别人的wp才写出来的;
关于异或,我们要知道这样一个技巧:
a ^ 0=a,a ^ a=0,那么可得:a ^ b ^ a=b,a ^ b ^ b = a;
由code[i]=code[i] ^ code[i+1],i从0取到l-1-1。处理后,code[l-1]没有变,那么要逆向,则令x从l-2取到0,使code[x]=code[x] ^ code[x+1](a ^ b ^ b = a) 。
关于取模,(a%c+b%c)=(a+b)%c,所以num等价于(input[i] +i)%128
解密脚本:
code = ['\x1f','\x12','\x1d','(','0','4','\x01','\x06','\x14','4',',','\x1b','U','?','o','6','*',':','\x01','D',';','%','\x13']l=len(code)
flag=' '
for i in range(l-2,-1,-1):code[i]=chr(ord(code[i])^ord(code[i+1]))for i in range(len(code)):flag+=chr((ord(code[i])-i)%128)print(flag)
得到flag为GWHT{Just_Re_1s_Ha66y!}
flag{Just_Re_1s_Ha66y!}
18.[GXYCTF2019]luck_guy
再写这题的时候已经是时隔一年了,没想过会再来搞逆向,不过来都来了,就做下吧
可以看到是64位文件,没有加壳
拖进IDA里面去看一下,先看main()函数
我们先会进入welcome()函数,点击welcome()函数看一下,啥也没有,回去看看函数patch_me()
看一下函数patch_me(),发现如果输入的数是偶数,就可以进入函数get_flag()
我们进入get_flag()看一下,可以看出来这就是我们需要分析代码的地方
读到这段代码的时候,就感觉有点奇怪,好像代码不是连续的,逻辑上就有点奇奇怪怪的
后来看了一些大佬的讲解,才知道代码给我这样感觉的原因。因为这里的switch-case
是随机的,所以可以不用管。
我们可以发现case1
就是flag
,flag是由f1和f2拼接得到的,而f1是固定的,只需要看f2就可以了。
我们可以看到case4中f2进行了定义,case5中对f2进行了处理
所以我们的顺序是4->5->1
我们上脚本,其实我一直不太理解这里的小端序大端序的问题,自己也没找到一些文章能帮助理解的
f2 = [0x69, 0x63, 0x75, 0x67, 0x60, 0x6f, 0x66, 0x7f] #小端序的问题,所以要逆序一下
flag = 'GXY{do_not_'for j in range(8):if (j % 2 == 1):flag += chr(f2[j] - 2)else:flag += chr(f2[j] - 1)print(flag)
19.[ACTF新生赛2020]easyre
还是先查查壳。
有壳,upx,拖到Linux里面去脱壳。
脱壳后的文件拖到IDA里面反编译一下,点击main()。
得到的伪代码
代码还算简单,但是我自己理解能力太差,看了好久还是没怎么看明白。
着眼观察for循环就行,从for循环了解到flag长度应该是12,
*(&v4 + i) !=data_start_[ *( ( char *)&v16 + i ) - 1] ) 的意思是在_data_start__字符串里面寻找一个字符然后 -1 与v4进行对比,注意括号的位置就能知道 -1 是减到索引还是索引值上,所以逆过来就是 +1。
python脚本
key = '~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)(\'&%$# !"' #'一定要加\
encrypt = [42,70,39,34,78,44,34,40,73,63,43,64]
x = []
flag = ''
for i in encrypt:x.append(key.find(chr(i))+1)
for i in x:flag += chr(i)
print(flag)
借鉴一下别人的脚本,自己写的错误百出。
最后flag为:
flag{U9X_1S_W6@T?}
20.CrackRTF
首先还是看看有没有加壳;
没有加壳,继续分析,拖到IDA里面看看。
这个代码真的是看的我头疼
自己看了好久也没有进展,看了几位大佬的wp;
if ( strlen((const char *)&pbData) != 6 ){printf("Must be 6 characters!\n");ExitProcess(0);}v5 = unknown_libname_1((char *)&pbData);if ( v5 < 100000 )
从这里可以看出我们的密码是六位的,点击unknown_libname_1函数,得到的是下图的函数
atol函数:用来将字符串转换成长整型数 ,并且转化后的整型要大于100000;
strcat((char *)&pbData, "@DBApp");
v0 = strlen((const char *)&pbData);
这个代码,第一行将 “ @DBApp ” 连接到密码的后面,第二行求出连接之后的密码为12;
sub_40100A(&pbData, v0, &String1)
sub_40100A是一个加密函数
memset(&v4, 0xCCu, 0x68u);if ( CryptAcquireContextA(&phProv, 0, 0, 1u, 0xF0000000) ){if ( CryptCreateHash(phProv, 0x8004u, 0, 0, &phHash) ){if ( CryptHashData(phHash, pbData, dwDataLen, 0) ){CryptGetHashParam(phHash, 2u, v7, &pdwDataLen, 0);*lpString1 = 0;for ( i = 0; i < pdwDataLen; ++i ){wsprintfA(&String2, "%02X", v7[i]);lstrcatA(lpString1, &String2);}CryptDestroyHash(phHash);CryptReleaseContext(phProv, 0);result = 1;}else{CryptDestroyHash(phHash);CryptReleaseContext(phProv, 0);result = 0;}}else{CryptReleaseContext(phProv, 0);result = 0;}}else{result = 0;}return result;
}
这加密函数看着就头疼;
CryptCreateHash(phProv, 0x8004u, 0, 0, &phHash)
搜索过后发现这个是哈希函数。
代码中的0x8004是标识符,并且是SHA1的算法
然后自己查了一下hashlib模块使用的方法
里面的16进制str类型的消息摘要,都是小写的英文字母
参考一下别人写的的代码
爆破代码如下:
import hashlib
string='@DBApp'
for i in range(100000,999999):flag=str(i)+stringx = hashlib.sha1(flag.encode("utf8"))y = x.hexdigest()if "6e32d0943418c2c33385bc35a1470250dd8923a9" == y:print(flag)break
得到密码为:123321@DBApp
所以我们知道前六位密码是123321
一些代码的讲解:
str通过encode()转换为bytes(二进制)
在python3中,encode()和decode()默认使用UTF-8
x.hexdigest()函数表示获得16进制str类型的消息摘要
第二部分和第一部分相类似,但是没有给我们范围,没办法爆破,只能自己慢慢看函数;
进入函数看到0x8003u,是MD5加密,但是解不出来;
再进入加密函数看一下
就没有正常一点的函数吗???
这一段代码的含义就是,从AAA文件中查找字符,然后如果没有找到就返回,找到了的话就计算出资源的大小,把资源第一个字符出的指针传给lpBuffer
这里我们可以用一个叫做ResourceHacker的工具来查看资源
但是还是看不懂;
往里面看看还有异或的函数:
a2就是AAA中得到的首部指针,v5是字符串的长度,也就是密码的长度。
整理一下,在进行异或完之后会生成一个RTF文件;
这个时候我们不妨打开一个RTF文件来查看它的头部
得到前六位是{\rtf1
再看资源的前六位是
资源的每一位和密码的每一位循环异或
异或结束之后,生成一个rtf文件
接下来这一步是我觉得很骚气 巧妙的一步
思考一下
我们的密码一共是6+12=18位
我们现在想要的是前六位的密码,循环异或的话,那么也就是说,资源的前六位与密码的前六位异或的结果就是rtf文件的前六位
这里的思想是借鉴的别人的
下面的脚本是借鉴别人的;
rtf = '{\\rtf1' \\需要注意,\r需要转义,变成\\r
A = [0x05, 0x7D, 0x41, 0x15, 0x26, 0x01]
password=''
for i in range(len(rtf)):x = ord(rtf[i]) ^ A[i]password+=chr(x)
print(password)
得到的结果为~!3a@0
第二段的密码为~!3a@0123321@DBApp
两端密码输入完后,就会在程序所在文件夹中生成一个带有flag的rtf文件,打开就能得到flag
flag为Flag{N0_M0re_Free_Bugs}
flag{N0_M0re_Free_Bugs}
21.[ACTF新生赛2020]rome
首先我们拖进虚拟机中,可以看到是32位文件
然后我们再放到IDA里面看看,找到伪代码
int func()
{int result; // eaxint v1; // [esp+14h] [ebp-44h]int v2; // [esp+18h] [ebp-40h]int v3; // [esp+1Ch] [ebp-3Ch]int v4; // [esp+20h] [ebp-38h]unsigned __int8 v5; // [esp+24h] [ebp-34h]unsigned __int8 v6; // [esp+25h] [ebp-33h]unsigned __int8 v7; // [esp+26h] [ebp-32h]unsigned __int8 v8; // [esp+27h] [ebp-31h]unsigned __int8 v9; // [esp+28h] [ebp-30h]int v10; // [esp+29h] [ebp-2Fh]int v11; // [esp+2Dh] [ebp-2Bh]int v12; // [esp+31h] [ebp-27h]int v13; // [esp+35h] [ebp-23h]unsigned __int8 v14; // [esp+39h] [ebp-1Fh]char v15; // [esp+3Bh] [ebp-1Dh]char v16; // [esp+3Ch] [ebp-1Ch]char v17; // [esp+3Dh] [ebp-1Bh]char v18; // [esp+3Eh] [ebp-1Ah]char v19; // [esp+3Fh] [ebp-19h]char v20; // [esp+40h] [ebp-18h]char v21; // [esp+41h] [ebp-17h]char v22; // [esp+42h] [ebp-16h]char v23; // [esp+43h] [ebp-15h]char v24; // [esp+44h] [ebp-14h]char v25; // [esp+45h] [ebp-13h]char v26; // [esp+46h] [ebp-12h]char v27; // [esp+47h] [ebp-11h]char v28; // [esp+48h] [ebp-10h]char v29; // [esp+49h] [ebp-Fh]char v30; // [esp+4Ah] [ebp-Eh]char v31; // [esp+4Bh] [ebp-Dh]int i; // [esp+4Ch] [ebp-Ch]v15 = 'Q';v16 = 's';v17 = 'w';v18 = 51;v19 = 115;v20 = 106;v21 = 95;v22 = 108;v23 = 122;v24 = 52;v25 = 95;v26 = 85;v27 = 106;v28 = 119;v29 = 64;v30 = 108;v31 = 0;printf("Please input:");scanf("%s", &v5);result = v5;if ( v5 == 'A' ){result = v6;if ( v6 == 'C' ){result = v7;if ( v7 == 'T' ){result = v8;if ( v8 == 'F' ){result = v9;if ( v9 == '{' ){result = v14;if ( v14 == '}' ){v1 = v10;v2 = v11;v3 = v12;v4 = v13;for ( i = 0; i <= 15; ++i ){if ( *((_BYTE *)&v1 + i) > 64 && *((_BYTE *)&v1 + i) <= 90 )*((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 51) % 26 + 65;if ( *((_BYTE *)&v1 + i) > 96 && *((_BYTE *)&v1 + i) <= 122 )*((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 79) % 26 + 97;}for ( i = 0; i <= 15; ++i ){result = (unsigned __int8)*(&v15 + i);if ( *((_BYTE *)&v1 + i) != (_BYTE)result )return result;}result = printf("You are correct!");}}}}}}return result;
}
凯撒加密+大小写互换,程序的意思就是,让我们输入一个字符串,然后判断大小写,进行相应的运算,最后得到了程序开头的数组
v15 = ['Q','s','w','3','s','j', '_','l','z','4','_','U','j','w','@','l']
看一下主要的运算代码
for ( i = 0; i <= 15; ++i ){if ( *((_BYTE *)&v1 + i) > 64 && *((_BYTE *)&v1 + i) <= 90 )*((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 51) % 26 + 65;if ( *((_BYTE *)&v1 + i) > 96 && *((_BYTE *)&v1 + i) <= 122 )*((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 79) % 26 + 97;}for ( i = 0; i <= 15; ++i ){result = (unsigned __int8)*(&v15 + i);if ( *((_BYTE *)&v1 + i) != (_BYTE)result )return result;}
我们这里用暴力破解
v15= [ 'Q','s','w','3','s','j', '_','l','z','4','_','U','j','w','@','l' ]
flag = ' 'for i in range(16):for j in range(128): #ascii表上有127个字符x=jif chr(x).isupper():x=(x-51)%26+65if chr(x).islower():x=(x-79)%26 +97if chr(x) == v15[i]:flag+=chr(j)
print('flag{'+flag+'}')
22.[FlareOn4]login
多多少少有点离谱的简单题,下载好附件,是一个网页,F12可以看到有一个类似于算法和密文的东西
我自己一开始的想法还是,就是看看能不能读懂这个类似算法的东西,但是看了半天发现无从下手。
但是我们仔细读代码,可以发现里面有一个rot,让我一下子联想到ROT13加密解密
然后我就直接在线找了一个网站,加密解密,就成功了,解密出来的就是flag
23.[2019红帽杯]easyRE
是64位程序并且没有加壳的
老样子拖进IDA看一下,打开字符串,看到有一些关键字
"x"键交叉引用,切换到关键代码
看一下切换到的代码
signed __int64 sub_4009C6()
{char *v0; // rsichar *v1; // rdisigned __int64 result; // rax__int64 v3; // ST10_8__int64 v4; // ST18_8__int64 v5; // ST20_8__int64 v6; // ST28_8__int64 v7; // ST30_8__int64 v8; // ST38_8__int64 v9; // ST40_8__int64 v10; // ST48_8__int64 v11; // ST50_8__int64 v12; // ST58_8int i; // [rsp+Ch] [rbp-114h]char v14; // [rsp+60h] [rbp-C0h]char v15; // [rsp+61h] [rbp-BFh]char v16; // [rsp+62h] [rbp-BEh]char v17; // [rsp+63h] [rbp-BDh]char v18; // [rsp+64h] [rbp-BCh]char v19; // [rsp+65h] [rbp-BBh]char v20; // [rsp+66h] [rbp-BAh]char v21; // [rsp+67h] [rbp-B9h]char v22; // [rsp+68h] [rbp-B8h]char v23; // [rsp+69h] [rbp-B7h]char v24; // [rsp+6Ah] [rbp-B6h]char v25; // [rsp+6Bh] [rbp-B5h]char v26; // [rsp+6Ch] [rbp-B4h]char v27; // [rsp+6Dh] [rbp-B3h]char v28; // [rsp+6Eh] [rbp-B2h]char v29; // [rsp+6Fh] [rbp-B1h]char v30; // [rsp+70h] [rbp-B0h]char v31; // [rsp+71h] [rbp-AFh]char v32; // [rsp+72h] [rbp-AEh]char v33; // [rsp+73h] [rbp-ADh]char v34; // [rsp+74h] [rbp-ACh]char v35; // [rsp+75h] [rbp-ABh]char v36; // [rsp+76h] [rbp-AAh]char v37; // [rsp+77h] [rbp-A9h]char v38; // [rsp+78h] [rbp-A8h]char v39; // [rsp+79h] [rbp-A7h]char v40; // [rsp+7Ah] [rbp-A6h]char v41; // [rsp+7Bh] [rbp-A5h]char v42; // [rsp+7Ch] [rbp-A4h]char v43; // [rsp+7Dh] [rbp-A3h]char v44; // [rsp+7Eh] [rbp-A2h]char v45; // [rsp+7Fh] [rbp-A1h]char v46; // [rsp+80h] [rbp-A0h]char v47; // [rsp+81h] [rbp-9Fh]char v48; // [rsp+82h] [rbp-9Eh]char v49; // [rsp+83h] [rbp-9Dh]char v50[32]; // [rsp+90h] [rbp-90h]int v51; // [rsp+B0h] [rbp-70h]char v52; // [rsp+B4h] [rbp-6Ch]char v53; // [rsp+C0h] [rbp-60h]char v54; // [rsp+E7h] [rbp-39h]char v55; // [rsp+100h] [rbp-20h]unsigned __int64 v56; // [rsp+108h] [rbp-18h]v56 = __readfsqword(0x28u);v14 = 73;v15 = 111;v16 = 100;v17 = 108;v18 = 62;v19 = 81;v20 = 110;v21 = 98;v22 = 40;v23 = 111;v24 = 99;v25 = 121;v26 = 127;v27 = 121;v28 = 46;v29 = 105;v30 = 127;v31 = 100;v32 = 96;v33 = 51;v34 = 119;v35 = 125;v36 = 119;v37 = 101;v38 = 107;v39 = 57;v40 = 123;v41 = 105;v42 = 121;v43 = 61;v44 = 126;v45 = 121;v46 = 76;v47 = 64;v48 = 69;v49 = 67;memset(v50, 0, sizeof(v50));v51 = 0;v52 = 0;v0 = v50;sub_4406E0(0LL, v50, 37LL);v52 = 0;v1 = v50;if ( sub_424BA0(v50) == 36 ){for ( i = 0; ; ++i ){v1 = v50;if ( i >= (unsigned __int64)sub_424BA0(v50) )break;if ( (unsigned __int8)(v50[i] ^ i) != *(&v14 + i) ){result = 4294967294LL;goto LABEL_13;}}sub_410CC0("continue!");memset(&v53, 0, 0x40uLL);v55 = 0;v0 = &v53;sub_4406E0(0LL, &v53, 64LL);v54 = 0;v1 = &v53;if ( sub_424BA0(&v53) == 39 ){v3 = sub_400E44((__int64)&v53);v4 = sub_400E44(v3);v5 = sub_400E44(v4);v6 = sub_400E44(v5);v7 = sub_400E44(v6);v8 = sub_400E44(v7);v9 = sub_400E44(v8);v10 = sub_400E44(v9);v11 = sub_400E44(v10);v12 = sub_400E44(v11);v0 = off_6CC090;v1 = (char *)v12;if ( !(unsigned int)sub_400360(v12, off_6CC090) ){sub_410CC0("You found me!!!");v1 = "bye bye~";sub_410CC0("bye bye~");}result = 0LL;}else{result = 4294967293LL;}}else{result = 0xFFFFFFFFLL;}
LABEL_13:if ( __readfsqword(0x28u) != v56 )sub_444020(v1, v0);return result;
}
先分析v50有关的代码,将用户输入与i异或后与在栈上存的数据进行比对
写脚本
v50 = [0x49,0x6F,0x64,0x6C,0x3E,0x51,0x6E,0x62,0x28,0x6F,0x63,0x79,0x7F,0x79,0x2E,0x69,0x7F,0x64,0x60,0x33,0x77,0x7D,0x77,0x65,0x6B,0x39,0x7B,0x69,0x79,0x3D,0x7E,0x79,0x4C,0x40,0x45,0x43]
flag=' 'for i in range(len(v50)):flag+=chr(v50[i]^i)
print(flag)
得到提示
然后我们接着看下半部分的代码
我们进入函数sub_400E44()看一下,经过观察我们可以看出来这是base64编码
我们找到编码过后的密文
找在线网站解码,给了我一个网址
毫无疑问的我们被骗了,啥也没有,这不是关键代码,这是障眼法
在第二次输入加密后对比的常量下面,还发现了一个常量,在sub_400D35函数中调用
交叉引用,看一下伪代码
仔细读这段代码,v5先与byte_6CC0A0这个数组的前四个值异或,然后在与v8异或得出flag,v5=v8,所以我们先求解v5
我们看一下数组byte_6CC0A0
写脚本
data1 = [0x66,0x6c,0x61,0x67]
data2 = [0x40,0x35,0x20,0x56]
data3 = [0x40,0x35,0x20,0x56,0x5D,0x18,0x22,0x45,0x17,0x2F,0x24,0x6E,0x62,0x3C,0x27,0x54,0x48,0x6C,0x24,0x6E,0x72,0x3C,0x32,0x45,0x5B]
v5='&YA1'
v8=[0x26,0x59,0x41,0x31]
flag=' 'for i in range(4):v5 += chr(data1[i]^data2[i])
print(v5)for i in range(25):flag += chr(data3[i]^v8[i%4])
print(flag)
运行后得出flag
24.[GUET-CTF2019]re
查壳工具看一下,发现有壳,是upx的
拖进kali里面脱壳
查一下可以看到是64位程序
我们再拖进IDA里面看一下,找到伪代码
观察代码可以发现,关键就是在sub_4009AE()这个函数上,点进去看一下
_BOOL8 __fastcall sub_4009AE(char *a1)
{if ( 1629056 * *a1 != 166163712 )return 0LL;if ( 6771600 * a1[1] != 731332800 )return 0LL;if ( 3682944 * a1[2] != 357245568 )return 0LL;if ( 10431000 * a1[3] != 1074393000 )return 0LL;if ( 3977328 * a1[4] != 489211344 )return 0LL;if ( 5138336 * a1[5] != 518971936 )return 0LL;if ( 7532250 * a1[7] != 406741500 )return 0LL;if ( 5551632 * a1[8] != 294236496 )return 0LL;if ( 3409728 * a1[9] != 177305856 )return 0LL;if ( 13013670 * a1[10] != 650683500 )return 0LL;if ( 6088797 * a1[11] != 298351053 )return 0LL;if ( 7884663 * a1[12] != 386348487 )return 0LL;if ( 8944053 * a1[13] != 438258597 )return 0LL;if ( 5198490 * a1[14] != 249527520 )return 0LL;if ( 4544518 * a1[15] != 445362764 )return 0LL;if ( 3645600 * a1[17] != 174988800 )return 0LL;if ( 10115280 * a1[16] != 981182160 )return 0LL;if ( 9667504 * a1[18] != 493042704 )return 0LL;if ( 5364450 * a1[19] != 257493600 )return 0LL;if ( 13464540 * a1[20] != 767478780 )return 0LL;if ( 5488432 * a1[21] != 312840624 )return 0LL;if ( 14479500 * a1[22] != 1404511500 )return 0LL;if ( 6451830 * a1[23] != 316139670 )return 0LL;if ( 6252576 * a1[24] != 619005024 )return 0LL;if ( 7763364 * a1[25] != 372641472 )return 0LL;if ( 7327320 * a1[26] != 373693320 )return 0LL;if ( 8741520 * a1[27] != 498266640 )return 0LL;if ( 8871876 * a1[28] != 452465676 )return 0LL;if ( 4086720 * a1[29] != 208422720 )return 0LL;if ( 9374400 * a1[30] == 515592000 )return 5759124 * a1[31] == 719890500;return 0LL;
}
这里就是相除,得到我们要的a1[]
脚本
a0 = 166163712 // 1629056
a1 = 731332800 // 6771600
a2 = 357245568 // 3682944
a3= 1074393000 // 10431000
a4= 489211344 // 3977328
a5 = 518971936 // 5138336
a6='_'
a7= 406741500 // 7532250
a8= 294236496 // 5551632
a9= 177305856 // 3409728
a10= 650683500 // 13013670
a11= 298351053 // 6088797
a12= 386348487 // 7884663
a13= 438258597 // 8944053
a14= 249527520 // 5198490
a15= 445362764 // 4544518
a16= 981182160 //10115280
a17= 174988800 // 3645600
a18= 493042704 // 9667504
a19= 257493600 // 5364450
a20= 767478780 // 13464540
a21= 312840624 // 5488432
a22= 1404511500 // 14479500
a23= 316139670 // 6451830
a24= 619005024 // 6252576
a25= 372641472 // 7763364
a26= 373693320 // 7327320
a27= 498266640 // 8741520
a28= 452465676 // 8871876
a29= 208422720 // 4086720
a30= 515592000 // 9374400
a31= 719890500 // 5759124print(chr(a0),chr(a1),chr(a2),chr(a3),chr(a4),chr(a5),a6,chr(a7),chr(a8),chr(a9),chr(a10),chr(a11),chr(a12),chr(a13),chr(a14),chr(a15),chr(a16),chr(a17),chr(a18),chr(a19),chr(a20),chr(a21),chr(a22),chr(a23),chr(a24),chr(a25),chr(a26),chr(a27),chr(a28),chr(a29),chr(a30),chr(a31))
我们缺少一位a6,现在得到的flag是flag{e65421110ba03099a1c039337},a6并没有给我们,那就从0开始一个一个试,到1的时候成功了
最后的flag为flag{e165421110ba03099a1c039337}
25.[WUSTCTF2020]level1
打开这个附件可以看到有两个文件
打开txt文档,看到的是一堆数字,暂时看不明白有啥用
我们打开另一个文件,首先看到是64位文件
拖进IDA里面看一下,代码非常简单,就是我们输入的数经过下面的运算,写到了txt文件中,单数是位移,偶数是乘法
我们逆着写一个代码,逆推回去,要注意i是从1开始的,但是数组的下标是从0开始的
看一下脚本
data = [198,232,816,200,1536,300,6144,984,51200,570,92160,1200,565248,756,1474560,800,6291456,1782,65536000]
flag = ' 'for i in range(1,20):if i&1:flag+=chr(data[i-1]>>i)else:flag+=chr(data[i-1] // i)
print(flag)
得到flag
本文标签: BUUCTF
版权声明:本文标题:BUUCTF 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1686816078h39079.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论