热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[BUUCTF]REVERSE——[网鼎杯2020青龙组]singal

[网鼎杯2020青龙组]singal附件步骤例行检查,32位程序,无壳本地试运行一下程序32位ida载入,首先是找到main函数确定

[网鼎杯 2020 青龙组]singal

附件

步骤


  1. 例行检查,32位程序,无壳
    在这里插入图片描述
  2. 本地试运行一下程序
    在这里插入图片描述
  3. 32位ida载入,首先是找到main函数确定了flag字符串的样式flag{……}
    在这里插入图片描述
    根据输入点的提示字符串,找到对应函数,确定了字符串的长度是15
    在这里插入图片描述
    右击该函数,找到调用该函数的地方,来到了vm_operad()函数处,看main函数可以知道,vm_operad里的参数v4在上面一行调用了qmemcpy函数,百度上说逆向里的qmemcpy=memcpy,memcpy在c语言里的拷贝函数,在unk_403040中拷贝了0x1C8字节的数据给v4
    unk_403040这个地址上有好多数据拷贝0x1C8个就是到0x403208
    在这里插入图片描述
    选中,shift+e转换成数组
    在这里插入图片描述
    4字节等于一个int,interl处理器是小端存储,刚好a1数组的值就是三个00之前那十六进制,整理一下得到
    v4=[10, 4, 16, 8, 3, 5, 1, 4, 32, 8, 5, 3, 1, 3, 2, 8, 11, 1, 12, 8, 4, 4, 1, 5, 3, 8, 3, 33, 1, 11, 8, 11, 1, 4, 9, 8, 3, 32, 1, 2, 81, 8, 4, 36, 1, 12, 8, 11, 1, 5, 2, 8, 2, 37, 1, 2, 54, 8, 4, 65, 1, 2, 32, 8, 5, 1, 1, 5, 3, 8, 2, 37, 1, 4, 9, 8, 3, 32, 1, 2, 65, 8, 12, 1]
    这里要注意32位程序存储的时候的小端序的问题,我这边先不逆序,下面还要找一下内存中处理的时候的一些数据

接着调用了该数组和114进入了vm_operad函数

int __cdecl vm_operad(int *a1, int _114)
{int result; // eaxchar Str[200]; // [esp+13h] [ebp-E5h] BYREFchar v4; // [esp+DBh] [ebp-1Dh]int v5; // [esp+DCh] [ebp-1Ch]int v6; // [esp+E0h] [ebp-18h]int v7; // [esp+E4h] [ebp-14h]int v8; // [esp+E8h] [ebp-10h]int v9; // [esp+ECh] [ebp-Ch]v9 = 0;v8 = 0;v7 = 0;v6 = 0;v5 = 0;while ( 1 ){result = v9;if ( v9 >= _114 )return result;switch ( a1[v9] ){case 1:Str[v6 + 100] = v4;++v9;++v6;++v8;break;case 2:v4 = a1[v9 + 1] + Str[v8];v9 += 2;break;case 3:v4 = Str[v8] - LOBYTE(a1[v9 + 1]);v9 += 2;break;case 4:v4 = a1[v9 + 1] ^ Str[v8];v9 += 2;break;case 5:v4 = a1[v9 + 1] * Str[v8];v9 += 2;break;case 6:++v9;break;case 7:if ( Str[v7 + 100] != a1[v9 + 1] ){printf("what a shame...");exit(0);}++v7;v9 += 2;break;case 8:Str[v5] = v4;++v9;++v5;break;case 10:read(Str);++v9;break;case 11:v4 = Str[v8] - 1;++v9;break;case 12:v4 = Str[v8] + 1;++v9;break;default:continue;}}
}

当值等于7时str数组的值会与a1数组的下一位进行比较,相等继续,不等报错。7后面的数字就是正确输入进行加密后需要与之比较的值,刚好7这个值在a1数组的最后,将这串值提取出来

str=[]
a1=[10, 4, 16, 8, 3, 5, 1, 4, 32, 8, 5, 3, 1, 3, 2, 8, 11, 1, 12, 8, 4, 4, 1, 5, 3, 8, 3, 33, 1, 11, 8, 11, 1, 4, 9, 8, 3, 32, 1, 2, 81, 8, 4, 36, 1, 12, 8, 11, 1, 5, 2, 8, 2, 37, 1, 2, 54, 8, 4, 65, 1, 2, 32, 8, 5, 1, 1, 5, 3, 8, 2, 37, 1, 4, 9, 8, 3, 32, 1, 2, 65, 8, 12, 1, 7, 34, 7, 63, 7, 52, 7, 50, 7, 114, 7, 51, 7, 24, 7, 167, 255, 255, 255, 7, 49, 7, 241, 255, 255, 255, 7, 40, 7, 132, 255, 255, 255, 7, 193, 255, 255, 255, 7, 30, 7, 122]
for i in range(0,len(a1)):if a1[i]==7:str.append(a1[i+1])print(a1)

在这里插入图片描述
str=[34, 63, 52, 50, 114, 51, 24, 167, 49, 241, 40, 132, 193, 30, 122]
然后switch里的其他case选项就是对str数组进行了操作,最后得到了str里面的值,逆向算法解一下

这里面有个LOBYTE这个函数,做的时候我去百度了有说是取最右边那位,有说右边四位,没有统一的说法,找了其他师傅的wp,说这是ida的函数,可以忽略这个函数。rax是64位寄存器,eax是32位寄存器,ax是16位寄存器,al是ax寄存器低8位,ah是ax寄存器高8位。
在这里插入图片描述

a1=[]
v4=[10, 4, 16, 8, 3, 5, 1, 4, 32, 8, 5, 3, 1, 3, 2, 8, 11, 1, 12, 8, 4, 4, 1, 5, 3, 8, 3, 33, 1, 11, 8, 11, 1, 4, 9, 8, 3, 32, 1, 2, 81, 8, 4, 36, 1, 12, 8, 11, 1, 5, 2, 8, 2, 37, 1, 2, 54, 8, 4, 65, 1, 2, 32, 8, 5, 1, 1, 5, 3, 8, 2, 37, 1, 4, 9, 8, 3, 32, 1, 2, 65, 8, 12, 1, 7, 34, 7, 63, 7, 52, 7, 50, 7, 114, 7, 51, 7, 24, 7, 167, 255, 255, 255, 7, 49, 7, 241, 255, 255, 255, 7, 40, 7, 132, 255, 255, 255, 7, 193, 255, 255, 255, 7, 30, 7, 122]
for i in range(0,len(v4)):if v4[i]==7:a1.append(v4[i+1])
#print(a1)a1 = [34, 63, 52, 50, 114, 51, 24, 167, 49, 241, 40, 132, 193, 30, 122]
a1.reverse()
v4.reverse()v9 = 0
us = 0
v5 = 0
flag = []
for i in range(0, len(v4)):if i == len(v4) - 1:flag.append(us)if v4[i] == 1 and v4[i - 1] != 1:v5 = a1[v9]v9 += 1flag.append(us)if v4[i] == 2:if (v4[i + 1] != 3 and v4[i + 1] != 4 and v4[i + 1] != 5):us = v5 - v4[i - 1]# print(us,v5,a[i-1])if v4[i] == 3:if (v4[i + 1] != 2 and v4[i + 1] != 4 and v4[i + 1] != 5):us = v5 + v4[i - 1] # LOBYTE是al有8位,参与运算的5、33、32是全值,所以LOBYTE可省略if v4[i] == 4:if (v4[i + 1] != 3 and v4[i + 1] != 2 and v4[i + 1] != 5):us = v5 ^ v4[i - 1]if v4[i] == 5:if (v4[i + 1] != 3 and v4[i + 1] != 4 and v4[i + 1] != 2):us = int(v5 / v4[i - 1])if v4[i] == 8:v5 = usif v4[i] == 11:us = v5 + 1if v4[i] == 12:us = v5 - 1# print("12:",us)flag.reverse()
out = ''
for j in flag:out += chr(j)
print("flag{" + out + "}")

flag{757515121f3d478 }


推荐阅读
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 本文由编程笔记#小编整理,主要介绍了关于数论相关的知识,包括数论的算法和百度百科的链接。文章还介绍了欧几里得算法、辗转相除法、gcd、lcm和扩展欧几里得算法的使用方法。此外,文章还提到了数论在求解不定方程、模线性方程和乘法逆元方面的应用。摘要长度:184字。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 怎么在PHP项目中实现一个HTTP断点续传功能发布时间:2021-01-1916:26:06来源:亿速云阅读:96作者:Le ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • 在Oracle11g以前版本中的的DataGuard物理备用数据库,可以以只读的方式打开数据库,但此时MediaRecovery利用日志进行数据同步的过 ... [详细]
author-avatar
大傻vv_528
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有