一.拖入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. Java安全之Cas反序列化漏洞分析

    Java安全之Cas反序列化漏洞分析 0x00 前言 某次项目中遇到Cas,以前没接触过,借此机会学习一波. 0x01 Cas 简介 CAS 是 Yale 大学发起的一个开源项目,旨在为 Web 应用 ...

  2. Centos 重置root密码

    # cat /etc/system-release                         #查看版本 开机后在内核grub.2上敲击 e 在linux16 行(倒数第二行)末加入 " ...

  3. 原型和原型链 prototype和proto的区别

    原型 原型是function对象下的属性,它定义了构造函数的共同祖先,也就是一个父子级的关系,子对象会继承父对象的方法和属性 prototype是函数下的属性,对象想要查看原型使用隐式属性__Prot ...

  4. jackjson学习2+CVE-2019-14379漏洞分析

    最近想着分析jackson,jackson和fastjson有点相似,浅蓝大神的文章很好,个人受益匪浅 昨天简单说了下jackson的用法,现在继续拓扑,补充前置知识,前置知识补充的足够多,那么漏洞分 ...

  5. 微星msi B450M+i5-8500+1060成功黑苹果

    经过几天的努力,终于成功装上黑苹果! N卡1060目前只能装10.13.6(17G65),10.14版本N卡是没有驱动的,即便装上后也是8M的显存 详细教程网上一大堆,我就不做一份了.推荐大家看一下黑 ...

  6. Redis限制一键登录次数

    一.产生背景 之前的随笔提到过项目中写了一键登录功能.上线后除了有时候网络波动会导致登陆失败,其他情况一直稳如老狗 しかし,邮件看到有人恶意刷一键登录,这年头闲的人可真闲啊, 只能思考如何搞一搞 二. ...

  7. nginx的请求处理

      nginx的请求处理¶ nginx使用一个多进程模型来对外提供服务,其中一个master进程,多个worker进程.master进程负责管理nginx本身和其他worker进程. 所有实际上的业务 ...

  8. 适用于AMD ROC GPU的Numba概述

    适用于AMD ROC GPU的Numba概述 Numba通过按照HSA执行模型将Python代码的受限子集直接编译到HSA内核和设备功能中,从而支持AMD ROC GPU编程.用Numba编写的内核似 ...

  9. 深度学习调用TensorFlow、PyTorch等框架

    深度学习调用TensorFlow.PyTorch等框架 一.开发目标目标 提供统一接口的库,它可以从C++和Python中的多个框架中运行深度学习模型.欧米诺使研究人员能够在自己选择的框架内轻松建立模 ...

  10. python_request 使用jsonpath取值结果,进行接口关联

    一.jsonpath的安装 pip   install  jsonpath 二.使用举例 import jsonpath d1={"token":"hjshdsjhdsj ...