攻防世界1

阅读须知:

探索者安全团队技术文章仅供参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作,由于传播、利用本公众号所提供的技术和信息而造成的任何直接或者间接的后果及损失,均由使用者
本人负责,作者不为此承担任何责任,如有侵权烦请告知,我们会立即删除并致歉,创作不易转载请标明出处.感谢!


first

题目地址:first

  1. ida打开,程序接受一个输入,随后进行异或,但并未对flag修改,最后异或的结果放入了v10(后面要用到):在这里插入图片描述
  2. 往后,又有一个循环里面执行了pthread_create函数,如下为这个函数的功能,其会创建一个线程,最重要的一个参数是该线程的入口函数start_routine:
  3. 进入start_routine函数查看具体功能,其将flag每4个分成一组进行加密encode_flag,如果加密后的结果v8[0]与byte_602120中的结果相等则将flag放入到res中。:在这里插入图片描述
  4. 注意在start_routine函数中有pthread_mutex_lock和pthread_mutex_unlock两个函数,函数功能如下,其作用是为了在同时运行多个线程时访问同一个(或多个)数据而产生错误,先给数据上锁的线程优先运行,其他线程在该线程解锁互斥量后才能运行,因此总的来时,先拿到flag的先运行,后拿到的后运行。但是start_routine中有个usleep(v3)函数,导致我们无法判断哪部分的flag先进行加密,所以要对解密出来的6部分flag进行组合,得到正确输入的flag:在这里插入图片描述
  5. 接下来关注加密函数encode_flag,可见时一个MD5加密,加密后的结果放在byte_602120中,可以直接进爆破,脚本如下:在这里插入图片描述
import hashlib
a=[ 0x47, 0x46, 0xBB, 0xBD, 0x02, 0xBB, 0x59, 0x0F, 0xBE, 0xAC, 0x28, 0x21, 0xEC, 0xE8, 0xFC, 0x5C, 0xAD, 0x74, 0x92, 0x65, 0xCA, 0x75, 0x03, 0xEF, 0x43, 0x86, 0xB3, 0x8F, 0xC1, 0x2C, 0x42, 0x27, 0xB0, 0x3E, 0xCC, 0x45, 0xA7, 0xEC, 0x2D, 0xA7, 0xBE, 0x3C, 0x5F, 0xFE, 0x12, 0x17, 0x34, 0xE8]
print(hashlib.md5("juhu".encode()).hexdigest())
check="4746bbbd2bb59fbeac2821ece8fc5cad749265ca753ef4386b38fc12c4227b03ecc45a7ec2da7be3c5ffe121734e8"
for i in range(6):for j in range(48,128):for k in range(48,128):for m in range(48,128):for n in range(48,128):tmp=chr(j)+chr(k)+chr(m)+chr(n)crypt=hashlib.md5(tmp.encode()).hexdigest()print(tmp)if crypt[0:16]==check[16*i:(i+1)*16]:print(tmp)#"juhuhfenlapsdunuhjifiuer"
  1. 后续一个循环等待线程结束:
  2. 后面应该是一窜异或加密后进行比较(防止输入不正确的flag来得到正确的res),最后只是对前面的res与byte_6020DF和v10进行了异或:
  3. 所以现在只需要知道v10,有之前的分析,v10与输入的flag有关,所以只需要组合出正确的flag即可通过脚本解密出v10,最后解密脚本如下:
res='juhuhfenlapsiuerhjifdunu'
v11=0
for i in range(len(res)):tmp=ord(res[i])+iv11^=tmp
flag="juhuhfenlapsdunuhjifiuer"
key=[0xFE, 0xE9, 0xF4, 0xE2, 0xF1, 0xFA, 0xF4, 0xE4, 0xF0, 0xE7, 0xE4, 0xE5, 0xE3, 0xF2, 0xF5, 0xEF, 0xE8, 0xFF, 0xF6, 0xF4, 0xFD, 0xB4, 0xA5, 0xB2]
for i in range(len(flag)):print(chr(ord(flag[i])^key[i]^v11),end="")
#goodjobyougetthisflag233

总结:有关线程的知识,入口函数设置,共享资源的占用,互斥量:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>// 共享资源
int count = 0;
// 互斥量
pthread_mutex_t lock;// 线程函数
void *print_hello1(void *arg)
{sleep(4); // 睡眠3秒,让2先拿到共享资源for (int i = 0; i < 10; i++){printf("%d", i);}pthread_mutex_lock(&lock); // 锁定共享资源count = 1;printf("\nHello from thread1!:%d\n", count);pthread_mutex_unlock(&lock); // 如果不解除共享资源,那么下一个线程永远不会开始return NULL;
}void *print_hello2(void *arg)
{sleep(3);pthread_mutex_lock(&lock);count = 2;printf("Hello from thread1!:%d\n", count);sleep(2);pthread_mutex_unlock(&lock);sleep(1);printf("hahahaha\n");return NULL;
}int main()
{pthread_t thread_id1, thread_id2; // 储存创建线程的IDint result1, result2;// 初始话互斥变量pthread_mutex_init(&lock, NULL);// 两个线程同时运行,但是遇到互斥量时,先拿到共享资源的线程优先执行result1 = pthread_create(&thread_id1, NULL, print_hello1, NULL); // 创建第一个线程result2 = pthread_create(&thread_id2, NULL, print_hello2, NULL); // 创建第二个线程if (result1 != 0){printf("Error creating thread.");exit(1);}pthread_join(thread_id1, NULL); // 等待线程结束pthread_join(thread_id2, NULL);printf("%d\n", thread_id1);printf("%d\n", thread_id2);printf("Thread joined.");// 销毁互斥变量pthread_mutex_destroy(&lock);return 0;
}

  1. 先锁定共享资源的线程会先运行,在其没有解锁共享资源时,其他线程都会被阻塞,但是在锁定共享资源前,线程都会同步运行下去,大家壳自行验证,线程是否阻塞是根据 互斥lock是否被上锁决定,在使用 pthread_mutex_lock(&lock);上锁之前会检查lock是否已经锁定,如果锁定则线程会被阻塞在pthread_mutex_lock(&lock)函数的位置,其上锁之前的部分不会受到影响(均可进行自行验证)。

game

题目地址:game

  1. 找到关键代码直接修改判断条件结束循环,直接输出flag:在这里插入图片描述
  2. 修改后如下:
  3. 随便按几下就会直接输出flag=zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}:

总结:game解题的关键

  1. 梳理好游戏的逻辑后,修改关键的判断语句代码或者直接修改RIP,来快速达成通关条件得到flag。

key

题目地址:key

  1. 看题目的描述,这题似乎要在程序种找到钥匙,打开门才行:
  2. 程序运行直接看蒙了,没有提示要接受输入,推测应该是在程序中打开文件直接读取的数据,或者程序要的输入(key)直接作为数据存储在程序中:
  3. ida打开查看逻辑,果然没有接受任何输入,开始有两端while循环对两个字符串进行了加密,并且只有这两个循环对其进行了修改:
  4. 往后看有一个sub_401620函数,进到里面发现打开了一个flag文件(与前面猜想的一样),打开文件后自然要判断打开是否成功,再读取文件中的内容(看文件名里面似乎就住着flag):在这里插入图片描述
  5. 由于这里给的路径是出题人本机的路径,我们可以在自己的主机上创建这路径并生成flag.txt文件,或者直接修改路径如下:
  6. 通过动态调试,后续的if语句就是判断文件是否打开成功,猜测后面的sub_D12E90函数是读取打开的文件中的内容,存放到v23,动态调试发现果然如此,后面应该时判断了读取是否成功。
  7. 最后,目的flag已经读取出来,并且程序中的字符串也解密完成,只需要比较即可,比较函数并没有直接给出,我们根据结果 “Congrats You got it!” 来反推,要达到 “Congrats You got it!”,v7必须是0,而v7是函数sub_4020C0的返回值,所以可以直接推断函数sub_4020C0就是比较函数:
  8. 虽然函数sub_4020C0中的逻辑一言难尽,但是不妨碍我们做出以上推测(或则可以在flag.txt文件中输入不同的字符串进行调试,来反推函数sub_4020C0的功能):
  9. 利用前的加密逻辑编写脚本即可解密出需要的key:
a=">----++++....<<<<."
key="themida"
for i in range(len(a)):print(chr((ord(a[i])^ord(key[i%len(key)]))+9+22),end="")
  1. 或者直接运行程序,然后再内存中查找,这里存放的位置并不在表面上的v29中,真的在哪里大家就自己区找喽:

最后来分析一下加密函数sub_4021E0:

  1. 看一下其中加密函数sub_4021E0的声明类型是 __thiscall,这种函数在传递参数的时候有一个特点,只会使用栈传参,且从右往左入栈,不会使用通用寄存器(另外还有其他类型的函数,如__fastcall约定的函数,其传递参数的方式都不相同,约定也都不一样,大家可自行学习):在这里插入图片描述

  1. 加密函数sub_4021E0ida表面上似乎解释错了,人家有三个接受输入,但是ida只传了两个(size和char a3),但是这个函数的this指针好像是个全局变量,查看调用这个函数的汇编代码个月发现其使用栈只传递了两个参数,this指针这参数根本没给,所以它可能是一个全局变量(所以才不用传参,直接默认了相当于),往全局变量里面放加密后的flag,那当然就不用额外再在程序中定义临时变量:

总结:程序逻辑或是函数功能看不清楚时,可以由最终的结果来反推flag或者动态调试来推断函数的功能。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

为了执行SQL语句,MySQL的架构是怎样设计的

1. 把MySQL当个黑盒子一样执行SQL语句 上一讲我们已经说到&#xff0c;我们的系统采用数据库连接池的方式去并发访问数据库&#xff0c;然后数据库自己其实也会维护一个连 接池&#xff0c;其中管理了各种系统跟这台数据库服务器建立的所有连接 我们先看下图回顾一下 当我们的…

苹果备忘录误删一段内容怎么恢复?iPhone备忘录恢复的4种方法!收藏!

在使用苹果设备时&#xff0c;备忘录是许多用户常用的工具之一。iPhone备忘录是一款功能强大、易于使用的应用&#xff0c;它能帮助你更好地管理生活和工作。无论你是记录待办事项、设置提醒还是与他人分享信息&#xff0c;备忘录都能满足你的需求。 然而&#xff0c;如果不小…

Mac下载的软件显示文件已损坏,如何解决文件已损坏问题

当在Mac上下载的软件显示文件已损坏时&#xff0c;这可能是因为多种原因导致的&#xff0c;包括网络问题、下载中断、软件未完整下载、文件传输错误等。解决这个问题需要采取一些步骤来排除可能的原因&#xff0c;并尝试修复文件。下面将详细介绍一些常见的解决方法&#xff1a…

单链表链表专题

1 链表的概念 概念&#xff1a;链表是⼀种物理存储结构上⾮连续、⾮顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 链表的结构跟⽕⻋⻋厢相似&#xff0c;淡季时⻋次的⻋厢会相应减少&#xff0c;旺季时⻋次的⻋厢会额外增加⼏节。只 需要…

Laravel 11入门:使用ServBay打造高效开发环境

Laravel 11发布&#xff0c;改进了不少功能。 它引入了更加流畅的应用结构、每秒限速、健康路由等特性。 此外&#xff0c;Laravel还推出了第一方可扩展的WebSocket服务器Laravel Reverb&#xff0c;为你的应用提供强大的实时功能。 在今天的指南中&#xff0c;我将设置一个…

【C语言__动态内存管理__复习篇6】

目录 前言 一、动态内存管理 二、动态内存函数 2.1 malloc 2.2 free 2.3 calloc 2.4 realloc 三、动态内存常见的6个使用错误 3.1 接收malloc/calloc返回的参数后未及时检查是否为NULL 3.2 越界访问动态内存空间 3.3 对非动态开辟的内存使用free释放 3.4 使用free只释放了…

「 典型安全漏洞系列 」14.NoSQL注入漏洞详解

NoSQL注入是一个漏洞&#xff0c;攻击者能够干扰应用程序对NoSQL数据库进行的查询&#xff0c;本文我们将研究如何测试一般的NoSQL漏洞&#xff0c;然后重点研究如何利用MongoDB中的漏洞&#xff08;MongoDB是最流行的NoSQL数据库&#xff09;。 1. 什么是NoSQL注入 NoSQL注入…

[lesson33]C++中的字符串类

C中的字符串类 历史遗留问题 C语言不支持真正意义上的字符串C语言用字符数组和一组函数实现字符串操作C语言不支持自定义类型&#xff0c;因此无法获得字符串类型 解决方案 从C到C的进化过程引入自定义类型在C中可以通过类完成字符串类型的定义 标准库中的字符串类 C语言直…

古月·ROS2入门21讲——学习笔记(一)核心概念部分1-14讲

讲解视频地址&#xff1a;1.ROS和ROS2是什么_哔哩哔哩_bilibili 笔记分为上篇核心概念部分和下篇常用工具部分 下篇&#xff1a;古月ROS2入门21讲——学习笔记&#xff08;二&#xff09;常用工具部分15-21讲-CSDN博客 目录 第一讲&#xff1a;ROS/ROS2是什么 1. ROS的诞生…

Java实现单点登录(SSO)详解:从理论到实践

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; ✨✨ 帅哥美女们&#xff0c;我们共同加油&#xff01;一起进步&am…

[docker] 核心知识 - 容器/镜像的管理和操作

[docker] 核心知识 - 容器/镜像的管理和操作 想要查看完整的指令&#xff0c;可以通过 docker --help 列举所有的指令&#xff0c;这里会提到一些比较常用的核心指令 查看容器的状态 这个应该是最常用的指令&#xff0c;语法为 docker ps&#xff0c; ps 为 process status …

【详解算法流程+程序】DBSCAN基于密度的聚类算法+源码-用K-means和DBSCAN算法对银行数据进行聚类并完成用户画像数据分析课设源码资料包

DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一个比较有代表性的基于密度的聚类算法。 与划分和层次聚类方法不同&#xff0c;它将簇定义为密度相连的点的最大集合&#xff0c;能够把具有足够高密度的区域划分为簇&#xff0c; 并可在噪声的空间数据…