BUUCTF reverse wp 56 - 60

news2024/11/26 0:35:50

[ACTF新生赛2020]SoulLike

在这里插入图片描述

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  char v5; // [rsp+7h] [rbp-B9h]
  int i; // [rsp+8h] [rbp-B8h]
  int j; // [rsp+Ch] [rbp-B4h]
  int flag_content[14]; // [rsp+10h] [rbp-B0h] BYREF
  char flag[110]; // [rsp+4Ah] [rbp-76h] BYREF
  unsigned __int64 v10; // [rsp+B8h] [rbp-8h]

  v10 = __readfsqword(0x28u);
  printf("input flag:");
  scanf("%s", &flag[6]);
  strcpy(flag, "actf{");
  v5 = 1;
  for ( i = 0; i <= 4; ++i )
  {
    if ( flag[i] != flag[i + 6] )
    {
      v5 = 0;
      goto next;
    }
  }
  if ( !v5 )
    goto failed;
next:
  for ( j = 0; j <= 11; ++j )
    flag_content[j] = flag[j + 11];
  if ( (unsigned __int8)sub_83A(flag_content) && flag[23] == '}' )
  {
    printf("That's true! flag is %s", &flag[6]);
    return 0LL;
  }
  else
  {
failed:
    printf("Try another time...");
    return 0LL;
  }
}

sub_83A太大了无法分析
在这里插入图片描述

强行让IDA分析大函数, 在IDA安装目录的cfg文件夹找到hexrays.cfg修改配置, 把MAX_FUNCSIZE改大点
在这里插入图片描述

在这里插入图片描述
重启再F5出来, 得到3k+行的代码

__int64 __fastcall sub_83A(_DWORD *a1)
{
  int i; // [rsp+1Ch] [rbp-44h]
  int v3[14]; // [rsp+20h] [rbp-40h]
  unsigned __int64 v4; // [rsp+58h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  *a1 ^= 0x2Bu;
  a1[1] ^= 0x6Cu;
  a1[2] ^= 0x7Eu;
  a1[3] ^= 0x56u;
  a1[4] ^= 0x39u;
  a1[5] ^= 3u;
  a1[6] ^= 0x2Du;
  a1[7] ^= 0x28u;
  a1[8] ^= 8u;
...
  v3[6] = 53;
  v3[7] = 110;
  v3[8] = 0;
  v3[9] = 19;
  v3[10] = 30;
  v3[11] = 56;
  for ( i = 0; i <= 11; ++i )
  {
    if ( v3[i] != a1[i] )
    {
      printf("wrong on #%d\n", (unsigned int)i);
      return 0LL;
    }
  }
  return 1LL;
}

基本都是xor操作, 不想硬逆的话(硬逆也不是不行, 万行以内均可硬逆), 可以copy到c代码进行爆破, 或者pwntools逐位爆破, 或者采用angr自动化分析flag
最简洁的是pwntools逐位爆破, (angr的方法内存不够跑不出

from pwn import *
import re

context.log_level = 'debug'
ended = False
flag = ['z' for _ in range(12)]
for i in range(12):
    if ended == True: break
    for ch in range(32, 127):
        io = process('./SoulLike')
        flag[i] = chr(ch)
        payload = 'actf{' + ''.join(flag) + '}'
        io.sendline(payload)
        recv_content = io.recvline()
        idx = re.findall(b'on #(.*?)\n', recv_content)[0]
        idx = int(idx)
        
        if b"That's true!" in recv_content:
            print(recv_content)
            ended = True
            break

        if idx != i: break
        io.close()    
io.close()

[GWCTF 2019]re3

$ file attachment
attachment: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=c3b276030138cc9e29a0244b296b8f005a487a77, stripped
void __fastcall __noreturn main(int a1, char **a2, char **a3)
{
  int i; // [rsp+8h] [rbp-48h]
  char s[40]; // [rsp+20h] [rbp-30h] BYREF
  unsigned __int64 v5; // [rsp+48h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  __isoc99_scanf("%39s", s);
  if ( (unsigned int)strlen(s) != 32 )
  {
    puts("Wrong!");
    exit(0);
  }
  mprotect(&dword_400000, 0xF000uLL, 7);
  for ( i = 0; i <= 223; ++i )
    *((_BYTE *)sub_402219 + i) ^= 0x99u;
  sub_40207B(&unk_603170);
  sub_402219(s);
}

unsigned __int64 __fastcall sub_40207B(__int64 a1)
{
  char v2[16]; // [rsp+10h] [rbp-50h] BYREF
  __int64 v3; // [rsp+20h] [rbp-40h] BYREF
  __int64 v4; // [rsp+30h] [rbp-30h] BYREF
  __int64 v5; // [rsp+40h] [rbp-20h] BYREF
  unsigned __int64 v6; // [rsp+58h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  sub_401CF9(&BASE64_table_603120, 64LL, v2);   // MD5
  sub_401CF9(&unk_603100, 20LL, &v3);
  sub_401CF9(&Prime_Constants_char_6030C0, 53LL, &v4);
  sub_401CF9(&MD5_Constants_4025C0, 256LL, &v5);
  sub_401CF9(v2, 64LL, a1);                     // MD5
  return __readfsqword(0x28u) ^ v6;
}

写个IDC脚本解密代码段

#include <idc.idc>
 
static main(void){
    auto i = 0;
    auto m = 0;
    for(i = 0x402219; i <= 0x402219 + 223; i=i+1){
        m = byte(i);
        patch_byte(i,m ^ 0x99);
    }
}

如果解密之后的汇编把 push rbpmov rbp, rsp隔开看成两个函数, 就先右键undefine再c, 再全选中后p定义函数, 此时F5就可以看到解密后的反编译伪代码
在这里插入图片描述

__int64 __fastcall sub_402219(__int64 input)
{
  unsigned int v2; // [rsp+18h] [rbp-D8h]
  int i; // [rsp+1Ch] [rbp-D4h]
  char v4[200]; // [rsp+20h] [rbp-D0h] BYREF
  unsigned __int64 v5; // [rsp+E8h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  sub_400A71((__int64)v4, (__int64)&unk_603170);
  sub_40196E((__int64)v4, input);               // AES
  sub_40196E((__int64)v4, input + 16);          // AES
  v2 = 1;
  for ( i = 0; i <= 31; ++i )
  {
    if ( *(_BYTE *)(i + input) != byte_6030A0[i] )
      v2 = 0;
  }
  return v2;
}

最后会和byte_6030A0已知的数组进行比较, 猜测经过的一串处理是某种加密, 用findcrypt插件查看密码函数特征
在这里插入图片描述
识别出处理unk_603170的函数是MD5和AES轮密钥函数, 处理input的函数是AES, 整体分析得到流程: MD5两次base64table得到的数值经过AES轮密钥加密得到key, 然后用key对输入的字符串高16位和低16位分别加密(因为不存在iv, 所以加密模式是ECB), 最后和byte_6030A0数组进行比较, key部分可以动调得到(跳过大段逆向)
在这里插入图片描述

另外记得chmod +x attachment
在这里插入图片描述

在这里插入图片描述

用原版调试
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

得到key就简单了, REV

from Crypto.Cipher import AES
from Crypto.Util.number import *

key = 0xCB8D493521B47A4CC1AE7E62229266CE
testval = 0xBC0AADC0147C5ECCE0B140BC9C51D52B46B2B9434DE5324BAD7FB4B39CDB4B5B
key = long_to_bytes(key)
testval = long_to_bytes(testval)
round = AES.new(key, mode=AES.MODE_ECB)
flag = round.decrypt(testval)
print(flag.decode())

[GXYCTF2019]simple CPP

在这里插入图片描述

这里主函数比较长, 不贴完整代码, 因为没有壳而且处理逻辑不直观还有exe不包含恶意代码, 可以考虑直接主机IDA动调
在IDA目录下的dbgsrv文件夹, 打开win64_remote64
在这里插入图片描述

IDA debug选项设置之后就可以动调
在这里插入图片描述

这里动调可以确定第一个异或逻辑的v12
在这里插入图片描述

在这里插入图片描述

调试时可以分析出这一段逻辑是在对中间值自身做移位叠加(其实就是颠倒存储顺序, 左移8位就是一个字节, buf的低字节存到高地址)
在这里插入图片描述接着需要绕过反调试, 在test eax, eax时设置eax为0
在这里插入图片描述

根据判断条件得知需要确定v26, v25, v31, v32; v20, v33的值
在这里插入图片描述

逆回去分析各个值
在这里插入图片描述

整理得到四个变量的方程组, 用z3求解

from z3 import *
 
v13, v14, v15, v16 = BitVecs('v13 v14 v15 v16',64)
s=Solver()

s.add(v14 & ~v16 == 0x11204161012)
s.add((v14 & ~v16) | (v15 & v16) | (v14 & ~v15) | (v16 & ~v15) == 0x3E3A4717373E7F1F)
s.add((v14 & ~v15) & (v16) | (v14) & ((v15 & v16) | v15 & ~v16 | ~(v15 | v16)) == 0x8020717153E3013)
s.add(((v14 & ~v16) | (v15 & v16) | v15 & v14) == (~v16 & v14 | 0xC00020130082C0C))
s.add(v13 == 0x32310600)
# s.add(((v14 & ~v16) | (v15 & v16) | (v14 & ~v15) | (v16 & ~v15)) ^ v13 == 0x3E3A4717050F791F)

s.check()
m = s.model()
for i in m:
    print("%s = 0x%x" % (i, m[i].as_long()))

'''
v16 = 0x3e3a460533286f0d
v14 = 0x8020717153e3013
v15 = 0xc0002213008acac
v13 = 0x32310600
'''

再把v13 ~ v16作为字节串处理, 进行高低端序颠倒处理的逆过程, 然后与i_will_check_is_debug_or_not进行xor还原flag (这里已知比赛时的hint: 第二部分字符串为e!P0or_a

L = []
L.append(hex(m[v16].as_long())[2:].rjust(16, '0'))
L.append(hex(m[v15].as_long())[2:].rjust(16, '0'))
L.append(hex(m[v14].as_long())[2:].rjust(16, '0'))
L.append(hex(m[v13].as_long())[2:-2])

print(L)
temp = []
for each in L:
    if each != '323106':
        for i in range(0, 16, 2):
            tmp = each[i: i + 2]
            tmp = int(tmp, 16)
            temp.append(tmp)
    else:
        for i in range(0, 6, 2):
            tmp = each[i: i + 2]
            tmp = int(tmp, 16)
            temp.append(tmp)

print(temp, len(temp))
string = 'i_will_check_is_debug_or_not'
flag = ''
hint = 'e!P0or_a'
for i in range(len(temp)):
    if i >= 8 and i < 16:
        flag += hint[i % 8]
    else:
        flag += chr(ord(string[i]) ^ temp[i])

print('flag{' + flag + '}')

[FlareOn5]Ultimate Minesweeper

在这里插入图片描述

打开dnSpy进行一波C#逆向

public MainForm() // 函数入口
{
	this.InitializeComponent();
	this.MineField = new MineField(MainForm.VALLOC_NODE_LIMIT); // 地雷初始化
	this.AllocateMemory(this.MineField); // 分配空间
	this.mineFieldControl.DataSource = this.MineField;
	this.mineFieldControl.SquareRevealed += this.SquareRevealedCallback; // 事件响应
	this.mineFieldControl.FirstClick += this.FirstClickCallback; 
	this.stopwatch = new Stopwatch();
	this.FlagsRemaining = this.MineField.TotalMines;
	this.mineFieldControl.MineFlagged += this.MineFlaggedCallback;
	this.RevealedCells = new List<uint>();
}

public MineField(uint size)
{
	this.Size = size;
	this.MinesPresent = new bool[(int)size, (int)size];
	this.MinesVisible = new bool[(int)size, (int)size];
	this.MinesFlagged = new bool[(int)size, (int)size];
}

private void AllocateMemory(MineField mf)
{
	for (uint num = 0U; num < MainForm.VALLOC_NODE_LIMIT; num += 1U)
	{
		for (uint num2 = 0U; num2 < MainForm.VALLOC_NODE_LIMIT; num2 += 1U)
		{
			bool flag = true;
			uint r = num + 1U;
			uint c = num2 + 1U;
			if (this.VALLOC_TYPES.Contains(this.DeriveVallocType(r, c)))
			{
				flag = false;
			}
			mf.GarbageCollect[(int)num2, (int)num] = flag;
		}
	}
}

// Token: 0x0600000C RID: 12 RVA: 0x00002348 File Offset: 0x00000548
private void SquareRevealedCallback(uint column, uint row)
{
	if (this.MineField.BombRevealed)
	{
		this.stopwatch.Stop();
		Application.DoEvents();
		Thread.Sleep(1000);
		new FailurePopup().ShowDialog();
		Application.Exit();
	}
	this.RevealedCells.Add(row * MainForm.VALLOC_NODE_LIMIT + column);
	if (this.MineField.TotalUnrevealedEmptySquares == 0)
	{
		this.stopwatch.Stop();
		Application.DoEvents();
		Thread.Sleep(1000);
		new SuccessPopup(this.GetKey(this.RevealedCells)).ShowDialog();
		Application.Exit();
	}
}

// Token: 0x0600000D RID: 13 RVA: 0x000023E4 File Offset: 0x000005E4
private string GetKey(List<uint> revealedCells)
{
	revealedCells.Sort();
	Random random = new Random(Convert.ToInt32(revealedCells[0] << 20 | revealedCells[1] << 10 | revealedCells[2]));
	byte[] array = new byte[32];
	byte[] array2 = new byte[]
	{
		245,
		75,
		65,
		142,
		68,
		71,
		100,
		185,
		74,
		127,
		62,
		130,
		231,
		129,
		254,
		243,
		28,
		58,
		103,
		179,
		60,
		91,
		195,
		215,
		102,
		145,
		154,
		27,
		57,
		231,
		241,
		86
	};
	random.NextBytes(array);
	uint num = 0U;
	while ((ulong)num < (ulong)((long)array2.Length))
	{
		byte[] array3 = array2;
		uint num2 = num;
		array3[(int)num2] = (array3[(int)num2] ^ array[(int)num]);
		num += 1U;
	}
	return Encoding.ASCII.GetString(array2);
}

GetKey应该是跟flag有关的函数, 不过这里会和随机数组进行异或, 静态分析不通则转换思路, 游戏的目标是点出三个非雷区格子, 而且C#逆向可以直接修改源码所以采取patch的方法解决这个exe, 把踩雷之后的处理逻辑注释掉然后全部保存为_patched.exe, 暴力找出目标格子
在这里插入图片描述

最后再重新运行连点出三个格子就跳flag了

[MRCTF2020]PixelShooter

在这里插入图片描述

APK逆向, 拖入jeb (一开始用jadx分析不了非java源码
发现java代码没有关键逻辑
搜索一下得知安卓unity游戏的核心逻辑一般位于main\assets\bin\Data\Managed\Assembly-CSharp.dll
可以直接得到flag
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1053493.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络协议--概述

1.2 分层 网络协议通常分不同层次进行开发&#xff0c;每一层分别负责不同的通信功能。一个协议族&#xff0c;比如TCP/IP&#xff0c;是一组不同层次上的多个协议的组合。 TCP/IP通常被认为是一个四层协议系统&#xff0c;如图1-1所示。每一层负责不同的功能&#xff1a; 1.链…

从零手搓一个【消息队列】实现消息在文件中的存储

文章目录 一、序列化 / 反序列化二、文件存储设计1, 队列目录2, 消息数据文件3, 消息统计文件 三、硬盘管理 -- 文件1, 创建 MessageFileManager 类2, createQueueFiles() 创建目录/文件3, deleteFiles() 删除目录/文件4, checkFileExists() 检查目录/文件是否存在5, readStat(…

MonkeyRunner自动化测试

一&#xff1a;简介 MonkeyRunner提供了一个API&#xff0c;使用此API写出的程序可以在Android代码之外控制Android设备和模拟器。通过monkeyrunner&#xff0c;您可以写出一个Python程序去安装一个Android应用程序或测试包&#xff0c;运行它&#xff0c;向它发送模拟击键&…

单目标应用:基于狐猴优化算法(Lemurs Optimizer,LO)的微电网优化调度MATLAB

一、狐猴优化算法 狐猴优化算法&#xff08;Lemurs Optimizer&#xff0c;LO&#xff09;由Ammar Kamal Abasi等人于2022年提出&#xff0c;该算法模拟狐猴的跳跃和跳舞行为&#xff0c;具有结构简单&#xff0c;思路新颖&#xff0c;搜索速度快等优势。 狐猴头体长约为30-45…

【通意千问】大模型GitHub开源工程学习笔记(2)--使用Qwen进行推理的示例代码解析,及transformers的库使用

使用Transformers来使用模型 如希望使用Qwen-chat进行推理,所需要写的只是如下所示的数行代码。请确保你使用的是最新代码,并指定正确的模型名称和路径,如Qwen/Qwen-7B-Chat和Qwen/Qwen-14B-Chat 这里给出了一段代码 from transformers import AutoModelForCausalLM, Aut…

Promise击鼓传花

Promise击鼓传花 Promise系列导航前言一、Promise.prototype.then()1.语法2.代码及说明&#xff08;1&#xff09;代码段&#xff1a;&#xff08;2&#xff09;代码段&#xff1a;&#xff08;3&#xff09;代码段&#xff1a;&#xff08;4&#xff09;代码段&#xff1a;&am…

select完成服务器并发

服务器 #include <myhead.h>#define PORT 4399 //端口号 #define IP "192.168.0.191"//IP地址//键盘输入事件 int keybord_events(fd_set readfds); //客户端交互事件 int cliRcvSnd_events(int , struct sockaddr_in*, fd_set *, int *); //客户端连接事件 …

cloudCompare教程:一、可视化、点、线编辑

依据高度等准则(都在Scalar Fields中)渲染点云&#xff08;首先要打开Tools -> Projection -> Export coordinate to SF&#xff09; 在上述准则之外的&#xff0c;设置为不显示&#xff1a; 软件的显示设置&#xff08;首先打开右边的彩色柱状图&#xff0c;点击左边属性…

Qt::工程框架-工具栏停靠|悬浮-QDockWidget

二维矢量动画智能制作软件开发合集 链接&#xff1a;软件开发技术分享及记录合集 个人开发二维矢量动画智能制作软件界面如下&#xff1a; ​目录 一、界面停靠原理 二、界面停靠代码实现 三、界面停靠软件测试视频 结束语 一、工具栏停靠|悬浮原理 本软件的窗口设置如下…

2023年中国肠胃炎用药行业现状分析:随着老龄化进程明显加速,市场规模同比增长7%[图]

急性肠胃炎是一种因为饮食不当而引起的消化系统疾病&#xff0c;通常是因为摄入了含有病原菌的变质食物&#xff0c;或者过量食用刺激性食物&#xff0c;从而导致肠胃道黏膜发生急性炎症反应&#xff1b;慢性肠胃炎是一种长期存在症状并持续引发胃黏膜和肠黏膜发生慢性炎症反应…

超声雷达传感器与三角定位

1.概述 超声波雷达的工作原理是通过超声波发射装置向外发出超声波&#xff0c;到通过接收器接收到发送过来超声波时的时间差来测算距离。 对温度敏感性&#xff0c;使得超声波的速度具有如下特性 或 2.超声波雷达车位探测与障碍物检测 汽车超声波类装配方案多为前后向共8个UP…

28269-2012 座椅用蛇形弹簧 技术条件

声明 本文是学习GB-T 28269-2012 座椅用蛇形弹簧 技术条件. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了用圆截面材料制造的座椅用蛇形弹簧的技术要求、试验方法、检验规则及标志、包装、 运输、贮存。 本标准适用于车辆座椅…

APA技术架构与说明

1.自动泊车的硬件架构 2.APA自动泊车辅助系统 1&#xff09;APA主要包括以下典型功能 &#xff08;1&#xff09;泊车入库&#xff1a;利用超声波雷达或环视摄像头实现车位识别&#xff0c;并计算出合适行驶轨迹&#xff0c;对车辆进行横向/纵向控制使车辆驶入车位&#xff1…

20分钟---Vue2->Vue3

Vue官网地址&#xff1a;gVue.js - The Progressive JavaScript Framework | Vue.js 选项式vs组合式 vue的两种风格&#xff0c;搬运官网源码&#xff1a; 选项式 API (Options API)​ 使用选项式 API&#xff0c;我们可以用包含多个选项的对象来描述组件的逻辑&#xff0c…

28295-2012 高温合金管材通用技术条件

声明 本文是学习GB-T 28295-2012 高温合金管材通用技术条件. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 1.1 本标准规定了经过热、冷加工生产的变形高温合金管材产品交货的技术要求、试验方法、检验规则 和交货条件等技术内容。 1.2 本标…

Linux常用指令(二)

目录 一、 删除空目录&#xff08;rmdir&#xff09; 二、ln 硬链接与软链接 三、新建空文件或更新文件的时间戳&#xff08;touch&#xff09; 四、比较文件内容的差异&#xff08;diff&#xff09; 五、显示当前时间或设置系统时间&#xff08;date&#xff09; 六、显…

关于解决 unable to start ssh-agent service, error :1058

前言 操作系统&#xff1a;win11 命令终端&#xff1a;Powershell 当我在终端输入命令 启动 ssh-agent 代理的时候 ssh-agent -s 很不幸出现了 unable to start ssh-agent service, error :1058以下错误 问题的解决 查看我们ssh-agent 服务是否运行&#xff0c;执行如下命令…

自动驾驶技术:现状与未来

自动驾驶技术&#xff1a;现状与未来 文章目录 引言自动驾驶技术的现状自动驾驶技术的挑战自动驾驶技术的未来结论结论 2023星火培训【专项营】Apollo开发者社区布道师倾力打造&#xff0c;包含PnC、新感知等的全新专项课程上线了。理论与实践相结合&#xff0c;全新的PnC培训不…

代码随想录刷题 Day 22

235. 二叉搜索树的最近公共祖先 具体思路就是当小于pq的时候就往右取遍历&#xff0c;当大于的时候就往左遍历&#xff1b; lass Solution { public:TreeNode* traversal(TreeNode* current, TreeNode* p, TreeNode* q) {if (current->val > p->val && curre…

企业风险管理策略终极指南

企业风险管理不一定是可怕的。企业风险管理是一个模糊且难以定义的主题领域。它涵盖了企业的多种风险和程序&#xff0c;与传统的风险管理有很大不同。 那么&#xff0c;企业风险管理到底是什么&#xff1f;在本文中&#xff0c;我们将确定它是什么&#xff0c;提出两种常见的…