一.拖入ida,静态分析

__int64 __fastcall sub_7FF65D4511A0(__int64 a1, __int64 a2)
{
signed __int64 v2; // rbx
signed __int64 v3; // rax
__int64 v4; // rax
__int64 v5; // r11
__int128 *v6; // r14
int v7; // edi
_BYTE *v8; // rsi
char v9; // r10
int v10; // edx
__int64 v11; // r8
unsigned __int64 v12; // rcx
signed __int64 v13; // rcx
unsigned __int64 v14; // rax
unsigned __int64 i; // rax
__int64 v16; // rax
size_t v17; // rsi
_BYTE *v18; // rbx
_BYTE *v19; // r9
signed int v20; // er11
char *v21; // r8
signed __int64 v22; // rcx
char v23; // al
signed __int64 v24; // r9
signed __int64 v25; // rdx
__int64 v26; // rax
size_t Size; // [rsp+20h] [rbp-48h]
__int128 v29; // [rsp+28h] [rbp-40h]
int v30; // [rsp+38h] [rbp-30h]
int v31; // [rsp+3Ch] [rbp-2Ch]
int Code[4]; // [rsp+40h] [rbp-28h]
int v33; // [rsp+50h] [rbp-18h] *(_OWORD *)Code = 0i64;
v33 = 0;
sub_7FF65D4518C0(std::cin, a2, Code); //根据cin,知道是在输入字符串,存入Code里面
v2 = -1i64;
v3 = -1i64;
do
++v3;
while ( *((_BYTE *)Code + v3) );
if ( v3 != 19 ) //字符串长度为19
{
sub_7FF65D451620(std::cout, "error\n");
_exit((unsigned __int64)Code);
}
v4 = sub_7FF65D451E5C(5ui64); //根据后面的判断是申请内存空间
v5 = *(_QWORD *)&::Code; //这里有点迷惑性,看似是输入的字符串,实际点进去就知道是个常量
v6 = (__int128 *)v4;
v7 = 0;
v8 = (_BYTE *)v4;
do
{
v9 = v8[(_QWORD)Code - v4];
v10 = 0;
*v8 = v9;
v11 = 0i64;
v12 = -1i64;
do
++v12;
while ( *(_BYTE *)(v5 + v12) );
if ( v12 )
{
do
{
if ( v9 == *(_BYTE *)(v5 + v11) )
break;
++v10;
++v11;
}
while ( v10 < v12 );
}
v13 = -1i64;
do
++v13;
while ( *(_BYTE *)(v5 + v13) );
if ( v10 == v13 )
_exit(v5);
++v8;
}
while ( (signed __int64)&v8[-v4] < 4 );
*(_BYTE *)(v4 + 4) = 0; //判断字符串的前四位在字符串常量中,基本判断出是flag
do
++v2;
while ( *((_BYTE *)Code + v2) ); //字符串常量长度为36
v14 = 0i64;
v29 = *v6;
while ( *((_BYTE *)&v29 + v14) )
{
if ( !*((_BYTE *)&v29 + v14 + 1) )
{
++v14;
break;
}
if ( !*((_BYTE *)&v29 + v14 + 2) )
{
v14 += 2i64;
break;
}
if ( !*((_BYTE *)&v29 + v14 + 3) )
{
v14 += 3i64;
break;
}
v14 += 4i64;
if ( v14 >= 0x10 )
break;
} //测试那段内存空间字符串的长度
for ( i = v14 + 1; i < 0x10; ++i ) //补齐16位,也就是128bits
*((_BYTE *)&v29 + i) = 0;
v16 = sub_7FF65D451AB0(Code, v2, &v29, &Size); //结合题目,和上面的基本判定是xxtea加密
v17 = Size;
v18 = (_BYTE *)v16;
v19 = (_BYTE *)sub_7FF65D451E5C(Size);
v20 = 1;
*v19 = v18[2];
v21 = v19 + 1;
v19[1] = *v18;
v19[2] = v18[3];
v19[3] = v18[1];
v19[4] = v18[6];
v19[5] = v18[4];
v19[6] = v18[7];
v19[7] = v18[5];
v19[8] = v18[10];
v19[9] = v18[8];
v19[10] = v18[11];
v19[11] = v18[9];
v19[12] = v18[14];
v19[13] = v18[12];
v19[14] = v18[15];
v19[15] = v18[13];
v19[16] = v18[18];
v19[17] = v18[16];
v19[18] = v18[19];
v19[19] = v18[17];
v19[20] = v18[22];
v19[21] = v18[20];
v19[22] = v18[23];
for ( v19[23] = v18[21]; v20 < v17; ++v21 ) //打乱了下加密字符串的顺序
{
v22 = 0i64;
if ( v20 / 3 > 0 )
{
v23 = *v21;
do
{
v23 ^= v19[v22++];
*v21 = v23;
}
while ( v22 < v20 / 3 );
}
++v20;
}
*(_QWORD *)&v29 = -4569681940847739698i64;
v24 = v19 - (_BYTE *)&v29;
*((_QWORD *)&v29 + 1) = 3819887636644928495i64;
v25 = 0i64;
v30 = -939386845;
v31 = -95004953;
do
{
if ( *((_BYTE *)&v29 + v25) != *((_BYTE *)&v29 + v25 + v24) ) //比较是否正确
_exit(v7 * v7);
++v7;
++v25;
}
while ( v25 < 24 );
v26 = sub_7FF65D451620(std::cout, "You win!");
std::basic_ostream<char,std::char_traits<char>>::operator<<(v26, sub_7FF65D4517F0);
return 0i64;
}

思路;

先找到最终正确的加密字符串
逆向那个异或的算法
再移位回来
再xxtea的解密,
得出flag



然后写脚本逆向回去就好了。

import struct
_DELTA = 0x9E3779B9
def _long2str(v, w):
n = (len(v) - 1) << 2
if w:
m = v[-1]
if (m < n - 3) or (m > n): return ''
n = m
s = struct.pack('<%iL' % len(v), *v)
return s[0:n] if w else s def _str2long(s, w):
n = len(s)
m = (4 - (n & 3) & 3) + n
s = s.ljust(m, "\0")
v = list(struct.unpack('<%iL' % (m >> 2), s))
if w: v.append(n)
return v def encrypt(str, key):
if str == '': return str
v = _str2long(str, True)
k = _str2long(key.ljust(16, "\0"), False)
n = len(v) - 1
z = v[n]
y = v[0]
sum = 0
q = 6 + 52 // (n + 1)
while q > 0:
sum = (sum + _DELTA) & 0xffffffff
e = sum >> 2 & 3
for p in range(n):
y = v[p + 1]
v[p] = (v[p] + ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))) & 0xffffffff
z = v[p]
y = v[0]
v[n] = (v[n] + ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[n & 3 ^ e] ^ z))) & 0xffffffff
z = v[n]
q -= 1
return _long2str(v, False) def decrypt(str, key):
if str == '': return str
v = _str2long(str, False)
k = _str2long(key.ljust(16, "\0"), False)
n = len(v) - 1
z = v[n]
y = v[0]
q = 6 + 52 // (n + 1)
sum = (q * _DELTA) & 0xffffffff
while (sum != 0):
e = sum >> 2 & 3
for p in range(n, 0, -1):
z = v[p - 1]
v[p] = (v[p] - ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))) & 0xffffffff
y = v[p]
z = v[n]
v[0] = (v[0] - ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[0 & 3 ^ e] ^ z))) & 0xffffffff
y = v[0]
sum = (sum - _DELTA) & 0xffffffff
return _long2str(v, True) res=[0xCE, 0xBC, 0x40, 0x6B, 0x7C, 0x3A, 0x95, 0xC0, 0xEF, 0x9B, 0x20, 0x20, 0x91, 0xF7, 0x02, 0x35, 0x23, 0x18, 0x02, 0xC8, 0xE7, 0x56, 0x56,0xFA]
dec=""
for i in range(7,-1,-1):
a=""
for j in range(3):
tmp=res[i*3+j]
for w in range(i):
tmp^=res[w]
a+=chr(tmp)
dec=a+dec
print(dec)
key="flag"+"\x00"*12
num=[2,0,3,1,6,4,7,5,10,8,11,9,14,12,15,13,18,16,19,17,22,20,23,21]
n=[0 for i in range(24)]
for i in range(24):
n[num[i]]=dec[i]
dec2="".join(n)
dec3=decrypt(dec2,key)
print(dec3)

buu 红帽杯 XX的更多相关文章

  1. buu 红帽杯easyre

    一.拖入ida静态分析 找到关键函数,然后 这步是可以得出前4个字符是flag,不知道为啥我这边的v15的内存地址为空,不然可以异或解出来的,ida日常抽风... 十次的base64加密,我用在线平台 ...

  2. [BUUCTF]REVERSE——[2019红帽杯]easyRE

    [2019红帽杯]easyRE 附件 步骤: ida载入,没有main函数,就先检索了程序里的字符串 发现了base64加密的特征字符串,双击you found me跟进,找到了调用它的函数,函数很长 ...

  3. 2019红帽杯部分wp

    xx 程序首先取输入的前4个字符作为xxtea加密的密钥之后进行xxtea加密.接着进行位置置换操作,然后又进行了以3个为一组的异或 首先逆向解出xxtea加密之后的结果 #include<st ...

  4. 2019 红帽杯 Re WP

    0x01 xx 测试文件:https://www.lanzous.com/i7dyqhc 1.准备 获取信息 64位文件 2.IDA打开 使用Findcrypt脚本可以看到 结合文件名是xx,因此猜测 ...

  5. 红帽杯-MISC-Advertising for Marriage

    convert -flip screenshot.png screensho1.png 本篇结合我上一博客https://www.cnblogs.com/qq3285862072/p/11869403 ...

  6. [转+自]关于PHP7的新特性(涉及取反和disabled_functions绕过)

    PHP7和PHP5上的安全区别 preg_replace()不再支持/e修饰符 利用\e修饰符执行代码的后门大家也用了不少了,具体看官方的这段描述: 如果设置了这个被弃用的修饰符, preg_repl ...

  7. web赛题2

    @上海赛wp 微信 和 https://www.ctfwp.com/articals/2019unctf.html 后续公告https://unctf.buuoj.cn/notice.html 必看! ...

  8. Misc题目

    @freebuff教程https://www.freebuf.com/column/196815.html @巅峰极客wp https://www.anquanke.com/post/id/18914 ...

  9. SQLi —— 逗号,空格,字段名过滤突破

    前言 出于上海大学生网络安全大赛的一道easysql,促使我积累这篇文章.因为放了大部分时间在Decade和Babyt5上,easysql一点没看,事后看了WP,发现看不懂怎么回事,于是了解了一番. ...

随机推荐

  1. 矩阵中的路径 DFS+剪枝

    给定一个 m x n 二维字符网格 board 和一个字符串单词 word .如果 word 存在于网格中,返回 true :否则,返回 false . 单词必须按照字母顺序,通过相邻的单元格内的字母 ...

  2. <fmt:formatDate> 标签,日期格式化问题(Day_24)

    一个时间显示问题,出生日期显示应为: yyyy-MM-dd,却显示: GMT格式(Wed Jun 15 00:00:00 CST 1983) 解决方案: 将图一改为图二. 图一: 图二: 最后: 注意 ...

  3. 通过Maven打jar包&运行

    运行命令:java -jar [包名] https://www.cnblogs.com/jinjiyese153/p/9374015.html

  4. 用golang刷LeetCode

    用golang刷LeetCode 用Go语言刷LeetCode记录,只是为了练习Go语言,能力有限不保证都是最优解,只能在此抛转引玉了. 数据结构和算法 数据结构和算法是程序员的命根子,没了命根子也就 ...

  5. Python+Selenium - windows安全中心的弹窗(账号登录)

    当出现如下图所示的 Windows安全中心弹窗,需要输入用户名和密码时 如何用Python+selenium跳过这个登录. 步骤: 1.在注册表中三个位置各添加两个东西:iexplore.exe 和 ...

  6. Python+Selenium+Appium+API学习使用过的命令

    adb devices 查看连接电脑的手机设备 weditor 启动uiautomatorviewer2元素定位工具 以下2个命令作用一样 adb shell dumpsys activity | f ...

  7. TVM性能评估分析(一)

    TVM性能评估分析(一) System Overview AutoTVM vs Auto-scheduler Table 1. Workflow Comparision Figure 1. Searc ...

  8. 通过Mellanox ConnectX NIC使用XDP加速

    通过Mellanox ConnectX NIC使用XDP加速 Accelerating with XDP over Mellanox ConnectX NICs XDP(eXpress Data Pa ...

  9. 孟老板 BaseAdapter封装 (二) Healer,footer

    BaseAdapter封装(一) 简单封装 BaseAdapter封装(二) Header,footer BaseAdapter封装(三) 空数据占位图 BaseAdapter封装(四) PageHe ...

  10. C# —— 点击按钮动态打开ComboBox

    网上搜索了好多资料,大多是重绘ComboBox或者使用自定义控件创建一个全新的ComboBox(并非基于window的ComboBox). 对于菜鸟的我,实现太麻烦,有些代码理解起来困难,但是项目比较 ...