re2
1.下载文件后解压,拖入pe无壳,32位
2. IDA32位,查看字符串,直接F5进入伪代码,主要内容及分析如下(其中scanf,print是n
键更改)
do
{
print("**************************我的Flag出了什么问题??**************************\n", v4);
print("您的一些重要数据被我们加密了,就算您叫破喉咙来也没有办法恢复。\n", v5);
print("**************************那有没有恢复的方法呢??**************************\n", v6);
print(
"有的。只能通过我们的财付通,支付宝服务才能恢复,我以人格担保,只要充钱,就能解密\n"
"\n",
v7);
print("做出你的选择:\n", v8);
print("1.充钱\n2.退出\n", v9);
scanf("%d", (char)v10);
if ( v10[0] == 1 )
{
v13 = fopen("flag.txt", "r"); // 要有flag.txt文件
if ( !v13 )
{
print("打开源文件失败!\n", v4);
getchar();
exit(0);
}
v12 = fopen("enflag.txt", "w"); // 要有enflag.txt文件
if ( !v12 )
{
print("找不到加密文件!\n", v4);
getchar();
exit(0);
}
print("\n请输入您的密钥:", v4);
scanf("%s", (char)&Str); //输入密钥
sub_401069(&Str, &Str1); // 点击进去观察,是对密钥进行了加密,包含函数sub_401A70
// 传入参数的顺序有助于我们更好的看到逆向的内容
sub_401028(&Str, v15, v14, v13, v12); // 里面包含了sub_4014E0函数,对enflag.txt内容进行操作
}
else if ( v10[0] == 2 )
{
v11 = 0;
}
else
{
print("\n操作不合法!\n\n", v4);
}
}
while ( v11 );
char __cdecl sub_401A70(char *Str, char *Str1)
{
char v3; // [esp+0h] [ebp-E4h]
signed int i; // [esp+D0h] [ebp-14h]
signed int v5; // [esp+DCh] [ebp-8h]
__CheckForDebuggerJustMyCode(&unk_40B027);
v5 = strlen(Str);
for ( i = 0; i < v5; ++i )
Str1[i] += Str[i] ^ 0x1F;
if ( !strcmp(Str1, "DH~mqqvqxB^||zll@Jq~jkwpmvez{") ) // 对密钥进行亦或1F后与该字符串相等
print("充值成功.\n", v3);
else
print("Error!\n", v3);
return *Str1;
}
int __cdecl sub_4014E0(char *Str, int a2, int a3, FILE *Stream, FILE *a5)
{
char v6; // [esp+0h] [ebp-D8h]
size_t v7; // [esp+D0h] [ebp-8h]
__CheckForDebuggerJustMyCode(&unk_40B027);
v7 = strlen(Str);
sub_4010F0(a2, Str, v7);
/* 传参时 a2为str,即输入的密钥,a3为密钥长度
// 此处是初始化key表
int __cdecl sub_401800(int a1, int a2, int a3)
{
int result; // eax
int j; // [esp+D0h] [ebp-14h]
int i; // [esp+DCh] [ebp-8h]
result = __CheckForDebuggerJustMyCode(&unk_40B027);
if ( a3 <= 256 )
{ // 当len(key<256)时,k[i] = key[i % Len_k];
for ( i = 0; i < 256; ++i )
{
*(_BYTE *)(i + a1) = *(_BYTE *)(a2 + i % a3);
result = i + 1;
}
}
if ( a3 > 256 )
{
for ( j = 0; j < 256; ++j )
{
*(_BYTE *)(j + a1) = *(_BYTE *)(j + a2);
result = j + 1;
}
}
return result;
}
*/
sub_4010C8(a3);
/* 对a3进行初始化,产生了一个 1~256 的s表
result = __CheckForDebuggerJustMyCode(&unk_40B027);
for ( i = 0; i < 256; ++i )
{
*(_BYTE *)(i + a1) = i;
result = i + 1;
}
return result;
*/
sub_40116D(a3, a2);
/* a3传入时参数为a1
// 产生的1~256的s表的简单swap操作
result = __CheckForDebuggerJustMyCode(&unk_40B027);
v5 = 0;
for ( i = 0; i < 256; ++i )
{
v5 = (*(unsigned __int8 *)(i + a2) + v5 + *(unsigned __int8 *)(i + a1)) % 256;
v4 = *(_BYTE *)(i + a1);
*(_BYTE *)(i + a1) = *(_BYTE *)(v5 + a1);
*(_BYTE *)(v5 + a1) = v4;
result = i + 1;
}
return result;
*/
sub_4010EB(a3, Stream, a5); // 看传入参数的顺序,此函数是对enflag.txt进行函数操作,包含了sub_4015E0函数
/* for循环将a1[v6]与a1[v7]进行交换,即对s表部分进行交换
int __cdecl sub_4015E0(int a1, FILE *Stream, FILE *a3)
{
int result; // eax
char v4; // [esp+103h] [ebp-35h]
char i; // [esp+11Bh] [ebp-1Dh]
int v6; // [esp+124h] [ebp-14h]
int v7; // [esp+130h] [ebp-8h]
__CheckForDebuggerJustMyCode(&unk_40B027);
v7 = 0;
v6 = 0;
for ( i = fgetc(Stream); ; i = fgetc(Stream) )
{
result = i;
if ( i == -1 )
break;
v7 = (v7 + 1) % 256;
v6 = (v6 + *(unsigned __int8 *)(v7 + a1)) % 256;
v4 = *(_BYTE *)(v7 + a1);
*(_BYTE *)(v7 + a1) = *(_BYTE *)(v6 + a1);
*(_BYTE *)(v6 + a1) = v4;
fputc(*(_BYTE *)((*(unsigned __int8 *)(v6 + a1) + *(unsigned __int8 *)(v7 + a1)) % 256 + a1) ^ i, a3);
}
return result;
}
*/
fclose(Stream);
fclose(a5);
return print("\n加密成功!\n您的充值金额不足。\n\n", v6);
- 将enflag.txt拖入010editor查看16进制数,复制出来,脚本跑出来即可
- RC4脚本
#include<stdio.h> void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k) //初始化函数 { int i = 0, j = 0; char k[256] = { 0 }; unsigned char tmp = 0; for (i = 0; i < 256; i++) { s[i] = i; k[i] = key[i % Len_k]; } for (i = 0; i < 256; i++) { j = (j + s[i] + k[i]) % 256; tmp = s[i]; s[i] = s[j]; s[j] = tmp; } } void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) //加解密 { unsigned char s[256]; rc4_init(s, key, Len_k); int i = 0, j = 0, t = 0; unsigned long k = 0; unsigned char tmp; for (k = 0; k < Len_D; k++) { i = (i + 1) % 256; j = (j + s[i]) % 256; tmp = s[i]; s[i] = s[j]; s[j] = tmp; t = (s[i] + s[j]) % 256; Data[k] = Data[k] ^ s[t]; } } int main() { unsigned char key[] = "[Warnning]Access_Unauthorized"; unsigned long key_len = sizeof(key) - 1; unsigned char data[] = { 0xC3,0x82,0xA3,0x25,0xF6,0x4C, 0x36,0x3B,0x59,0xCC,0xC4,0xE9,0xF1,0xB5,0x32,0x18,0xB1, 0x96,0xAe,0xBF,0x08,0x35}; rc4_crypt(data, sizeof(data), key, key_len); for (int i = 0; i < sizeof(data); i++) { printf("%c", data[i]); } // flag{RC4&->ENc0d3F1le} printf("\n"); }
CrackRTF
-
查壳,拖入32位IDA,F5如下
int __cdecl main_0(int argc, const char **argv, const char **envp) { DWORD v3; // eax DWORD v4; // eax char Str[260]; // [esp+4Ch] [ebp-310h] BYREF int v7; // [esp+150h] [ebp-20Ch] char String1[260]; // [esp+154h] [ebp-208h] BYREF char n1[260]; // [esp+258h] [ebp-104h] BYREF memset(n1, 0, sizeof(n1)); memset(String1, 0, sizeof(String1)); v7 = 0; printf("pls input the first passwd(1): "); scanf("%s", n1); if ( strlen(n1) != 6 ) { printf("Must be 6 characters!\n"); ExitProcess(0); } v7 = atoi(n1); // 将输入的字符串转为数字串 if ( v7 < 100000 ) ExitProcess(0); strcat(n1, "@DBApp"); // 拼接字符串 v3 = strlen(n1); sub_40100A((BYTE *)n1, v3, String1); // 对串进行加密,点击进去发现 HASH 字样,应该是哈希算法加密的到的 if ( !_strcmpi(String1, "6E32D0943418C2C33385BC35A1470250DD8923A9") ) // 加密后得到的串 { printf("continue...\n\n"); printf("pls input the first passwd(2): "); memset(Str, 0, sizeof(Str)); scanf("%s", Str); // 再次输入,位第二段flag if ( strlen(Str) != 6 ) { printf("Must be 6 characters!\n"); ExitProcess(0); } strcat(Str, n1); //将上次输入以及拼接的123321@DBApp再次拼接到新的输入Str中 memset(String1, 0, sizeof(String1)); // 同样是hash函数 v4 = strlen(Str); sub_401019((BYTE *)Str, v4, String1); if ( !_strcmpi("27019e688a4e62a649fd99cadaafdb4e", String1) ) { if ( !(unsigned __int8)sub_40100F(Str) ) { printf("Error!!\n"); ExitProcess(0); } printf("bye ~~\n"); } } return 0; }
atol()
: 把字符串转换成长整型数用 法: long atol(const char *nptr); 返回长整型
atoll()
: 把字符串转换成长长整型数用 法: long long atol(const char *nptr); 返回长长整型
size_t fread ( void *buffer, size_t size, size_t count, FILE *stream)
; 返回真实读取的项数,count是最多读取的项数 -
哈希碰撞flag1
import hashlib flag = "@DBApp" for i in range(100000,999999): s = str(i)+flag x = hashlib.sha1(s.encode()) cnt = x.hexdigest() if "6e32d0943418c2c33385bc35a1470250dd8923a9" in cnt: print(cnt) print(str(i)+flag) # 123321@DBApp
-
分析flag2
CryptCreateHash函数的第二个参数用来确定哈希函数的类型
0x8004 -> SHA1, 0x800c -> SHA256, 0x8003 -> MD5
所以第一个密码是爆破SHA1,爆破范围是0-100000,爆破结果是123321
而第二个是MD5,但是除了后面的12位123321@DBApp
前面6位没有给提示,爆破显然不太实际,接着向下看sub_40100F
函数,同样是对输入的Str进行函数操作
FindResource
确定模块中指定类型和名称的资源所在的位置
如果函数运行成功,那么返回值为指定资源信息块的句柄,可以将这个句柄传递给LoadResource函数来获得这些资源,如果函数运行失败,则返回值为NULLSizeOfResource
获取指定资源的字节数LoadResource
装载指定资源到全局存储器LockResource
锁定资源并得到资源在内存中第一个字节的指针总体来说就是
sub_401005
函数将str与AAA查找的文件内容进行亦或,并将最终结果写入rft文件中;
利用resource hacker查看资源AAA
当然trf前面的文件肯定是文件头了,随便打开一个ttf文件取其前6位亦或即可
rtf = '{\\rtf1' a = [0x05, 0x7D, 0x41, 0x15, 0x26, 0x01] passwd='' for i in range(len(rtf)): x = ord(rtf[i]) ^ a[i] passwd+=chr(x) print(passwd) # ~!3a@0
-
得到一个dbapp.rtf的word文档,打开获得flag
Flag{N0_M0re_Free_Bugs}
resource hack使用介绍
FindResource,LoadResource,LockResource简单说明
[2019红帽杯]easyRE
-
PE查壳,拖入IDA64位,发现全是sub函数,查看字符串,找到如下名称,进入主函数F5反汇编主要如下
-
亦或反过来,得到输入的flag(上面的v12与v13合起来恰好是36位)
v12 = [73, 111, 100, 108, 62, 81, 110, 98, 40, 111, 99, 121, 127, 121, 46, 105, 127, 100, 96, 51, 119, 125, 119, 101, 107, 57, 123, 105, 121, 61, 126, 121, 76, 64, 69, 67] flag = '' for i in range(len(v12)): flag+=chr(v12[i] ^ i) print(flag) # Info:The first four chars are `flag`
-
说的好像是废话一样,hh那就是废话,接着向下看
sub_400E44
函数是base64加密,懂得都懂,进行了10次的base64加密得到v11,最终将v11与off_6CC90进行比较,接下来…
base64解密import base64 a = 'Vm0wd2VHUXhTWGhpUm1SWVYwZDRWVll3Wkc5WFJsbDNXa1pPVlUxV2NIcFhhMk0xVmpKS1NHVkdXbFpOYmtKVVZtcEtTMUl5VGtsaVJtUk9ZV3hhZVZadGVHdFRNVTVYVW01T2FGSnRVbGhhVjNoaFZWWmtWMXBFVWxSTmJFcElWbTAxVDJGV1NuTlhia0pXWWxob1dGUnJXbXRXTVZaeVdrWm9hVlpyV1hwV1IzaGhXVmRHVjFOdVVsWmlhMHBZV1ZSR1lWZEdVbFZTYlhSWFRWWndNRlZ0TVc5VWJGcFZWbXR3VjJKSFVYZFdha1pXWlZaT2NtRkhhRk5pVjJoWVYxZDBhMVV3TlhOalJscFlZbGhTY1ZsclduZGxiR1J5VmxSR1ZXSlZjRWhaTUZKaFZqSktWVkZZYUZkV1JWcFlWV3BHYTFkWFRrZFRiV3hvVFVoQ1dsWXhaRFJpTWtsM1RVaG9hbEpYYUhOVmJUVkRZekZhY1ZKcmRGTk5Wa3A2VjJ0U1ExWlhTbFpqUldoYVRVWndkbFpxUmtwbGJVWklZVVprYUdFeGNHOVhXSEJIWkRGS2RGSnJhR2hTYXpWdlZGVm9RMlJzV25STldHUlZUVlpXTlZadE5VOVdiVXBJVld4c1dtSllUWGhXTUZwell6RmFkRkpzVWxOaVNFSktWa1phVTFFeFduUlRhMlJxVWxad1YxWnRlRXRXTVZaSFVsUnNVVlZVTURrPQ==' for i in range(10): a = base64.b64decode(a).decode("utf-8") #必须先转码成byte型,因为python3中字符都为unicode编码,但是b64encode函数的参数为byte类型 print(a) #https://bbs.pediy.com/thread-254172.htm
-
解密出一个网站,访问后什么也找不到,返回IDA接着观看内容
右键,查找引用,都用到了sub_6CCA0
函数,再次交叉引用,观察其从哪调用,发现其是来自.fini_array
段处
.init中的代码在main之前执行
.finit中的代码在main之后执行
.init and .fini讲解 -
HIBYTE()
函数的作用是获取高字节也就是数组的最后一位,同时还有BYTE()
、BYTE1()
、BYTE2()
第一个是获取数组的第一位,第二个就是获取第二位,依次类推。猜测其为
flag
四个字符,这也印证了前面获得的那四个字符
-
其中
sub_410E90()
函数是对以上的数组进行亦或v4[j%4]
,所以要对v4进行反求解,得到原v4数组arr = [0x40, 0x35, 0x20, 0x56] v4 = '' res = 'flag' for i in range(4): v4 += chr(ord(res[i])^arr[i])
-
byte_6CC0A0
数组与v4[j%4]
进行亦或,得到flaga=[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] c=[] for i in range(len(a)): print(chr(a[i]^ord(v4[i%4])),end="")
[GUET-CTF2019]re
- PE查壳,发现upx壳,直接脱壳就行了
- 进入main函数
__int64 sub_400E28() { const char *v0; // rdi __int64 result; // rax __int64 v2; // rdx unsigned __int64 v3; // rt1 __int64 v4; // [rsp+0h] [rbp-30h] __int64 v5; // [rsp+8h] [rbp-28h] __int64 v6; // [rsp+10h] [rbp-20h] __int64 v7; // [rsp+18h] [rbp-18h] unsigned __int64 v8; // [rsp+28h] [rbp-8h] v8 = __readfsqword(0x28u); v4 = 0LL; v5 = 0LL; v6 = 0LL; v7 = 0LL; sub_40F950((__int64)"input your flag:", 0LL, 0LL, 0LL, 0LL); sub_40FA80((__int64)"%s", &v4); if ( (unsigned int)sub_4009AE(&v4, &v4) ) { v0 = "Correct!"; sub_410350("Correct!"); } else { v0 = "Wrong!"; sub_410350("Wrong!"); } result = 0LL; v3 = __readfsqword(0x28u); v2 = v3 ^ v8; if ( v3 != v8 ) sub_443550(v0, &v4, v2); return result; }
- 发现主要内容
correct
,进入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; }
- 反过来求flag即可
# -*- coding:utf-8 -*- a1 = chr(166163712 // 1629056) a2 = chr(731332800 // 6771600) a3 = chr(357245568 // 3682944) a4 = chr(1074393000 // 10431000) a5 = chr(489211344 // 3977328) a6 = chr(518971936 // 5138336) a8 = chr(406741500 // 7532250) a9 = chr(294236496 // 5551632) a10 = chr(177305856 // 3409728) a11 = chr(650683500 // 13013670) a12 = chr(298351053 // 6088797) a13 = chr(386348487 // 7884663) a14 = chr(438258597 // 8944053) a15 = chr(249527520 // 5198490) a16 = chr(445362764 // 4544518) a17 = chr(981182160 // 10115280) a18 = chr(174988800 // 3645600) a19 = chr(493042704 // 9667504) a20 = chr(257493600 // 5364450) a21 = chr(767478780 // 13464540) a22 = chr(312840624 // 5488432) a23 = chr(1404511500 // 14479500) a24 = chr(316139670 // 6451830) a25 = chr(619005024 // 6252576) a26 = chr(372641472 // 7763364) a27 = chr(373693320 // 7327320) a28 = chr(498266640 // 8741520) a29 = chr(452465676 // 8871876) a30 = chr(208422720 // 4086720) a31 = chr(515592000 // 9374400) a32 = chr(719890500 // 5759124) print (a1,a2,a3,a4,a5,a6,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32) # flag{e165421110ba03099a1c039337}