news 2026/6/15 17:41:19

Polar-reverse

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Polar-reverse

一.简单

1.reserve_fib

下载附件,得到一个程序和一个.txt文件,先用Die查一下程序壳,发现没有壳,然后用 IDA64 位查看一下

分析一下代码

int __fastcall main(int argc, const char **argv, const char **envp) { FILE *v3; // rax unsigned __int64 v4; // rbx unsigned __int64 v5; // rax unsigned __int64 v6; // rax __int64 v7; // rdx __int64 v8; // r10 __int64 v9; // r8 __int64 v10; // r9 __m128 v11; // xmm0 __m128i v12; // xmm0 __m128i v13; // xmm0 __m128i v14; // xmm0 unsigned int v15; // r9d int v17; // [rsp+30h] [rbp-108h] char Buffer[2]; // [rsp+40h] [rbp-F8h] BYREF __int16 v20[111]; // [rsp+42h] [rbp-F6h] print("please put your flag: "); v3 = _acrt_iob_func(0); fgets(Buffer, 100, v3); v4 = -1i64; do ++v4; while ( Buffer[v4] ); if ( v4 && Buffer[v4 - 1] == 10 ) { v5 = v4 - 1; v4 = v5; if ( v5 >= 0x64 ) goto LABEL_21; Buffer[v5] = 0; } print("Please enter the correct number of characters: "); get("%d",v17); getchar(); v6 = 0i64; if ( v17 > 0 ) { v7 = 1i64; if ( v17 != 1 && v17 != 2 ) { v8 = 1i64; v9 = 1i64; v10 = (unsigned int)(v17 - 2); do { v7 = v9 + v8; v8 = v9; v9 = v7; --v10; } while ( v10 ); } } else { v7 = 0i64; } v11 = (__m128)_mm_unpacklo_epi64((__m128i)(unsigned __int64)v7, (__m128i)(unsigned __int64)v7); if ( v4 ) { if ( v4 < 8 ) goto LABEL_24; v12 = (__m128i)_mm_and_ps(v11, (__m128)xmmword_1400032E0); v13 = _mm_packus_epi16(v12, v12); v14 = _mm_packus_epi16(v13, v13); v15 = _mm_packus_epi16(v14, v14).m128i_u16[0]; do { *(__int16 *)((char *)&v20[55] + v6) = _mm_cvtsi128_si32( _mm_sub_epi8( _mm_cvtsi32_si128(*(unsigned __int16 *)&Buffer[v6]), _mm_cvtsi32_si128(v15))); *(__int16 *)((char *)&v20[56] + v6) = _mm_cvtsi128_si32( _mm_sub_epi8( _mm_cvtsi32_si128(*(unsigned __int16 *)((char *)v20 + v6)), _mm_cvtsi32_si128(v15))); *(__int16 *)((char *)&v20[57] + v6) = _mm_cvtsi128_si32( _mm_sub_epi8( _mm_cvtsi32_si128(*(unsigned __int16 *)((char *)&v20[1] + v6)), _mm_cvtsi32_si128(v15))); *(__int16 *)((char *)&v20[58] + v6) = _mm_cvtsi128_si32( _mm_sub_epi8( _mm_cvtsi32_si128(*(unsigned __int16 *)((char *)&v20[2] + v6)), _mm_cvtsi32_si128(v15))); v6 += 8i64; } while ( v6 < (v4 & 0xFFFFFFFFFFFFFFF8ui64) ); if ( v6 < v4 ) { LABEL_24: do { *((_BYTE *)&v20[55] + v6) = Buffer[v6] - v7; ++v6; } while ( v6 < v4 ); } } if ( v4 >= 0x64 ) LABEL_21: sub_140001438(); *((_BYTE *)&v20[55] + v4) = 0; print("your flag is: %s\n"); return 0; }

这段代码看起来是有点不好分析,我刚做的时候也是找不到什么入手点,然后最上面的部分先不看,先分析一下主要的逻辑
程序输出 "please put your flag:",然后从标准输入读取v3,将v3的内容最多存储 99 个字节到Buffer里面
程序输出 "Please enter the correct number of characters: ",将用户输入存进v17里面

这段代码是经典的斐波那契数列迭代计算逻辑,斐波那契数列是 一个从0和1开始,每一项等于前两项之和的数列,一般定义 F(0)=0,F(1)=1,F(2)=1,这段代码里一开始的v7是第三项,v8 和 v9 是第一项和第二项,相加后v8变成了第二项,v9变成了第三项,v7又变成第二项加第三项,以此类推,满足斐波那契数列,因此我们输入的数字会经过斐波那契运算最后得到一个新的v7

这段代码表示将斐波那契运算得到的v7与我们输入的密文进行运算,因此我们的明文就是用密文加v7

看一下附件的内容

得到的这个字符串应该是斐波那契字符串,也就是我们的密文,要得到v17,一个一个试太慢了,因此直接找一个代码爆破一下

看到得到明文 wobuxiangjiaban ,然后要用md5加密,得到最终结果

2.re数独

下载解压压缩包,得到一个.exe文件,查壳发现没有壳,用IDA打开分析一下

int 表示返回整数类型,__fastcall 是一种调用约定,表示前几个参数通过寄存器传递
int v4[9][9] 定义了一个int型二维数组,数组大小为9*9
sizeof():计算变量或数据类型在内存中所占的字节数
qmemcpy(v4, &unk_403040, sizeof(v4)):将地址unk_403040里面存储的值的前v4个字节数复制到v4数组里
如果v4经过solveSudoku()函数得到的值是1,则输出GOOD,如果不是,则输出 No solution exists
那么接下来我们要看一下solveSudoku()的功能

这里要了解一下对 int (*a1)[9] 的理解,首先 *a1 表示一个指针,int *a1 表示指向一个整型一维数组,a1每加一就向后移动四个字节,int (*a1)[9] 表示指针a1指向一个每一行包含9个int类型元素的二维数组,当执行 a1 +1 时,编译器会认为要跳到 下一行
(*a1)[9*i+j] 使用*来解引用,将这个含有9个int类型元素的数组的第i行j类的值取出

这个函数定义了一个字符变量v3,变量的值为1
在数组v4里进行遍历循环,如果取到某个元素为0,则让v3为0,然后跳出内层循环
跳出内层循环后v3为0,此时满足v3!=1,然后再跳出外层循环
此时v3为0,依旧不会执行return 1i64,继续下一轮新的循环
循环9次,如果isSafe(a1,i,j,k)函数返回1,则让i行j列的元素值为k,然后再执行条件判断,如果solveSudoku返回1,这里也返回1,结束代码,如果返回0,让i行j列的元素值为0,也就是将填入的k值清零,再执行循环和isSafe()函数
如果isSafe()函数返回0,则重新执行循环
当循环9次之后发现还是不能满足条件,就会执行return 0i64

这里涉及到isSafe()函数,我们再查看一下这个函数

[9 * ( a2 - a2 % 3) + 9 * ( i / 3) + a3 - a3 %3 + i % 3] = [9 * ( a2 - a2 % 3 + i / 3) + ( a3 - a3 % 3 + i % 3 ) ] 这里也涉及到数独的一个知识,因为数独的九宫格是严格按照每 3 行一组来划分的,因此a2 - a2 % 3 得到的是行号a2所在的组的第一行,因为 i 取 0-8,所以 i / 3 的值为 0,1,2,a3 - a3 % 3 得到的是列号a3所在的组的第一列, i / 3 的值为 0,1,2,所以这里其实是实现了一个将这个9 * 9 的数组划分成9个 3 * 3 的数组,然后a2和a3定位了每一个 3 * 3 数组的左上角,然后使用 i 遍历这个 3 * 3 数组的每一个元素

isSafe()函数的功能就是,遍历a2行查看是否有元素的值为a4,遍历a3列查看是否有元素的值为a4,遍历这些 3 * 3 数组,查看是否有元素的值为a4,如果这三个条件有任意一个满足,则返回0
再回到solveSudoku()函数,可以知道isSafe()函数的参数是a1,i,j,k,i,j的值为solveSudo()函数循环中,v4数组中元素值为0的i和j

总结一下这个函数的功能,先遍历循环查看这个v4数组,如果查找到元素为0,则将该位置的 行号i 和 列号j 放到isSafe()函数里面进行修改,并且这个v4数组要满足每行每列不能有重复,而且每个 3 * 3 数组内不能用重复

第一步就是先查看一下这个v4数组,先提取得到v4数组

这里要注意 db 表示这是一个单字节的值,但是v4数组是一个int型数组,而int型是四个字节,因此提取时要四个字节为一个int型

最后使用脚本来解密

求出md5值

3.tanchi

下载解压压缩包,得到一个.exe程序,运行一下这个程序

这个程序是一个贪吃蛇游戏,先查壳看一下

发现是NsPack壳,脱一下壳,用IDA打开分析一下,找到一个函数内有疑似flag加密后的内容

先来分析一下:

将 `}{gvhBYnllosllYZsZsBkkAooslAiiiskAls 复制到数组v50里,v29是一个指向字符串的指针变量,它指向数组v50的首地址,然后就是进行循环,这是第一层解密,将v28的值与0x23异或,将异或得到的结果存到v29指向的地址里,然后 v29 指向数组v50的下一个位置,然后v28的值就是v29指向的内存的值

第二层解密,v30的值是数组v50的首地址里面的值,还有两个指向字符串的指针变量,分别是v31和v49,他们指向上一轮循环得到的新v50数组的首地址,用v30的值的ASCII码减去97(a)得到的值,然后再与25比较,通过这个来判断是不是小写字母,如果小于25,即是小写字母,则执行else分支,v32=(v30-76)%26+97,它的原型是 在凯撒密码中,如果把字母向前偏移5位,得到的就是 v32=(v30-97-5)%26+97,也就是v32=(v30-102)%26+97,因为在取模运算中,减去一个 26 的整数倍,得到的余数是完全相同的,所以 (v30-102)%26+97 等价于 (v30-76)%26+97,如果大于25,即非小写字母,就会执行下面的 if 判断,用v30的值的ASCII码减去65(A)得到的值,然后再与25比较,通过这个来判断是不是大写字母,如果大于25,即不是大写字母,跳到LABLE_53,如果小于25,即是大写字母,执行v32=(v30-44)%26+97,也是向前偏移5位,然后将得到的v32的值先写入到数组的首地址的内存中,然后又让指针v31指向v49指向的地址,然后执行LABEL_53,v33的值为v31指向的下一个内存的值,然后v49的值为自增后的v31的值,v30的值为v31的值

第三层解密,v34的值为数组v50的首地址的值,指针v35执行数组v50的首地址,v36是v34经过计算得到的值,让指针v35指向的地址内的元素的值为v36,如果v36的值小于32,会将v36的值加上32,再存到v35指向的内存里,然后让v37的值为v35自增后的内存的里的值,v34的值为v37的值

写一个解密脚本,得到flag

4.练习1

先查壳

没有壳,用IDA打开分析一下

代码的意思是,将密文复制给Str,使用memset函数将0复制到指针v6指向的内存的前50个字节,循环5次,将Str的前5个值存到数组v6里,然后从第6个值开始,前7个与7异或,后7个与8异或,然后得到flag

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/11 14:51:33

抖音评论批量采集终极指南:一键获取完整评论数据的简单方法

抖音评论批量采集终极指南&#xff1a;一键获取完整评论数据的简单方法 【免费下载链接】TikTokCommentScraper 项目地址: https://gitcode.com/gh_mirrors/ti/TikTokCommentScraper 还在为手动复制抖音评论而烦恼吗&#xff1f;无论你是内容创作者、运营人员还是市场分…

作者头像 李华
网站建设 2026/6/11 23:33:17

中文RAG失效根因与成本可视化实战指南

1. 项目概述&#xff1a;这不是一份 newsletter&#xff0c;而是一张AI学习者的“认知地图”“Learn AI Together — Towards AI Community Newsletter #25”——看到这个标题&#xff0c;你第一反应可能是&#xff1a;又一份每周发来的AI资讯汇总&#xff1f;点开就扫两眼&…

作者头像 李华
网站建设 2026/6/12 0:24:05

LLM 多轮对话状态管理:从上下文窗口优化到会话持久化

LLM 多轮对话状态管理&#xff1a;从上下文窗口优化到会话持久化一、上下文窗口的"挤牙膏"困境&#xff1a;长对话场景的核心瓶颈 大模型应用在多轮对话场景中面临一个根本性矛盾&#xff1a;对话历史越长&#xff0c;模型理解越准确&#xff0c;但 Token 消耗也越大…

作者头像 李华
网站建设 2026/6/12 6:42:30

Hanime1Plugin终极指南:3步解锁Android观影新体验

Hanime1Plugin终极指南&#xff1a;3步解锁Android观影新体验 【免费下载链接】Hanime1Plugin Android插件(https://hanime1.me) (NSFW) 项目地址: https://gitcode.com/gh_mirrors/ha/Hanime1Plugin 你是否厌倦了在Android设备上观看视频时的广告干扰和功能限制&#x…

作者头像 李华
网站建设 2026/6/12 14:28:46

网约车聚合平台技术选型:地图服务选错,直接拖慢上线 3 个月

前言 最近半年接触了 3 个做网约车聚合平台的创业团队&#xff0c;无一例外都在地图服务上栽了跟头。最夸张的一个团队&#xff0c;App 核心功能都开发完了&#xff0c;却因为地图相关的问题硬生生拖了 3 个月才上线&#xff0c;不仅错过了最佳的市场窗口&#xff0c;还多花了…

作者头像 李华