逆向学习笔记 之 drinkSomeTea

admin 2024年8月24日23:34:06评论31 views字数 3809阅读12分41秒阅读模式

写在前面

​ 这两天一直再看逆向相关的书,也在B站上看小甲鱼的视频学了一下OD(Ollydbg),但一直还没有实际尝试过逆向的解题,今天刚好是DASCTF的march月赛,所以做了其中一道比较简单的逆向题来入了个门。

​ 源程序在这里,这里应该是有三个解法,首先我先介绍方法一

method 1th

首先用IDA载入,

逆向学习笔记 之 drinkSomeTea

流程很简单,我们看到main(我按了一下反斜杠键,看着清爽些)

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
int __cdecl main(int argc, const char **argv, const char **envp){  HANDLE v3; // eax  void *v4; // esi  int result; // eax  DWORD v6; // edi  char *v7; // esi  DWORD v8; // ebx  HANDLE v9; // eax  void *v10; // esi  DWORD NumberOfBytesRead; // [esp+Ch] [ebp-8h] BYREF  DWORD NumberOfBytesWritten; // [esp+10h] [ebp-4h] BYREF  sub_401000(); sub_4013B2(aWelcomeToMyTea); v3 = CreateFileA(FileName, 0xC0000000, 0, 0, 3u, 0x80u, 0);  v4 = v3;  if ( v3 == -1 )  {    sub_4013B2(aIThinkYouDoNot);   result = 0;  }  else  {    v6 = GetFileSize(v3, 0);    if ( v6 < 0xEA60 )    {      SetFilePointer(v4, 0, 0, 0);      NumberOfBytesRead = 0;      ReadFile(v4, &unk_409988, v6, &NumberOfBytesRead, 0);      CloseHandle(v4);      if ( v6 >> 3 )      {        v7 = &unk_409988;        v8 = v6 >> 3;        do        {          (loc_4010A0)(v7, &unk_407030);          v7 += 8;          --v8;        }        while ( v8 );      }      v9 = CreateFileA(aTeaPngOut, 0xC0000000, 0, 0, 2u, 0x80u, 0);      v10 = v9;      if ( v9 == -1 )      {        sub_4013B2(aIThinkYouDoNot);     }      else      {        NumberOfBytesWritten = 0;        WriteFile(v9, &unk_409988, v6, &NumberOfBytesWritten, 0);        CloseHandle(v10);        sub_4013B2(aNowThisCupOfTe);     }      result = 0;    }    else    {      sub_4013B2(aYourTeaIsTooHo);     result = 0;    }  }  return result;}

逻辑很简单:

首先读入一个文件tea.png【判断是否读入成功,否则退出】

获取文件大小【如果文件大于等于0xEA60字节,退出】

然后将文件大小除以8,作为循环躺数(以8字节为单位对文件内容进行加密)

【加密函数】(文件地址,&unk_407030(key))

最后写入一个新的文件tea.png.out。

那我们就来看看这个加密函数

逆向学习笔记 之 drinkSomeTea

这里发现IDA反编译失败了,此时,要么就去啃汇编,要么就去找到原因

继续往下拉会发现逆向学习笔记 之 drinkSomeTea

这里有个神奇的指令,看不懂,据说是什么花指令(这个坑以后填叭),void教我的,在这里先按U(undefined),然后把00401116处 的值改为90(在hex-view里,F2,改掉,F2保存),也就是nop掉,

然后往上找push ebp【函数起点】,按p,创建函数

逆向学习笔记 之 drinkSomeTea

然后就可以快乐F5了

逆向学习笔记 之 drinkSomeTea

可以发现这个函数的两个参数,一个是int类型的指针(4字节),一个是_DWORD类型的指针(4字节)

并且在这里的操作中,我们可以看到,对第一个参数只用了a1[0],a1[1]这两个参数,对第二个参数,是用到了四个值

我们在思考一下这两个参数原本的意义,一个是8字节的文件,另一个是key,去看一下key

逆向学习笔记 之 drinkSomeTea

发现是个字符串,数一数是有16个字节的,所以估计是4个字节为一组作为一个_DWORD,那么第一个参数就是4个字符为一组作为一个int。然后在加密函数里进行操作。

那么字符怎么转换为数字呢?在.data块按d键就可以转化类型了,转化之后是

逆向学习笔记 之 drinkSomeTea

可以发现这个顺序怪怪的,是小端序,所以对于文件的数据而言,也是用的小端序了。

这里是对于前八字节的加密代码(我们能确定png文件的前八字节)

1234567891011121314151617181920212223
int main() {    int key[4] = { 0x67616C66, 0x6b61667b, 0x6c665f65, 0x7d216761 };    int v3 = 0; // [esp+Ch] [ebp-14h]    int i; // [esp+14h] [ebp-Ch]    int v5; // [esp+18h] [ebp-8h]    int v6; // [esp+1Ch] [ebp-4h]    int m[2] = { 0x474e5089, 0x0a1a0a0d };     v5 = 0;    v6 = m[1];    v3 = m[0];    for (i = 0; i < 32; ++i)    {        printf("%x %x %x\n", v5, v3, v6);        v5 -= 0x61C88647;        v3 += (key[1] + (v6 >> 5)) ^ (v5 + v6) ^ (key[0] + 16 * v6);        v6 += (key[3] + (v3 >> 5)) ^ (v5 + v3) ^ (key[2] + 16 * v3);    }    m[1] = v6;    m[0] = v3;    printf("%x %x %x\n", v5, v3, v6);    return 0;}

运行结果

逆向学习笔记 之 drinkSomeTea

逆向学习笔记 之 drinkSomeTea

可以看到,前八字节的密文与他给的加密文件的头八字节是一致的。那么至此我们已经可以选择写这个算法的解密算法了。

这就是方法一,解密脚本暂时没有,因为C语言快忘光了,不怎么会操作,python写起来又不太对,python复现加密

1234567891011121314151617
#encfrom Crypto.Util.number import *v5=0key = [0x67616C66, 0x6b61667b, 0x6c665f65, 0x7d216761]m = [0x474e5089, 0x0a1a0a0d]v3 = m[0]v6 = m[1]for j in range(32):    print(hex(v5),hex(v3),hex(v6))    v5 += 0x9E3779B9    v5 &= 0xffffffff    v3 += (key[1] + (v6 >> 5) ^ (v5 + v6)) ^ (key[0] + 16 * v6)    v3 &= 0xffffffff    v6 += (key[3] + (v3 >> 5) ^ (v5 + v3)) ^ (key[2] + 16 * v3)    v6 &= 0xffffffffprint(hex(v3),hex(v6))

结果

逆向学习笔记 之 drinkSomeTea

第三行的v6开始出错,估计是sar的问题,也就是那个算术位移操作【带符号的】

所以就放弃了,我选择patch这个程序,让他从加密程序,变成解密程序。

method 2nd

他的加密逻辑很简单,

先加v5

然后处理v3【v3与v5和v6有关】

最后处理v6【v6与v5和已经被处理的v3有关】

那么解密逻辑也不难,

先处理v6【最后的v6与最后的v5,v3的值有关,且这两个值已知,所以v6可以还原为上一轮的值】

然后处理v3【最后的v3与最后v5和上一轮的v6值有关,上一轮的v6值我们已经处理出来了,最后的v5我们也知道,因此v3也可以还原为为上一轮的值】

然后v5减去那个常数

所以我们可以选择从底层(汇编)改他的程序流程

但是比赛的时候我又失败了,改流程得稍微处理下,最后我是在原程序的基础上,patch了程序处理的值

method 3rd

把v5的初始值改为v5的最终值,然后把v5的add改为sub,那么程序一开始就是sub一下,意味着v5的值一开始就会被还原为上一轮,这是我们不期望的,我们还没用它呢,所以我们得在v5的最终值的基础上,在加一轮先【也就是改成第33轮的v5】,方便程序去sub

然后就是把v3 patch成v6,把v6 patch成v3。

与此同时我们也要把他们用到的key调换一下,但调换的时候会遇到问题,好像是代码的长度对不上,那么我们就直接在.data段【hex-view】把key前后两段的顺序换一下,这样效果还是一样的。

结果为

逆向学习笔记 之 drinkSomeTea

逆向学习笔记 之 drinkSomeTea

注:patch:【Edit-Patch Program-Asemble】

​ patch的时候给v5赋值的时候要用dword ptr,不然会报错

逆向学习笔记 之 drinkSomeTea

​ patch完了保存【Edit-Patch Program-Apply patches to input file】

这样子这个程序就变成了解密程序了,将加密图片的后缀去掉,点击这个程序,然后就会生成一个tea.png.out文件,再把这个文件后缀去掉,就是flag的图片了。

patch好的程序也一起塞着这里

【回头补一下前两个方法的做法】

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可联系QQ 643713081,也可以邮件至 [email protected] - source:Van1sh的小屋

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年8月24日23:34:06
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   逆向学习笔记 之 drinkSomeTeahttp://cn-sec.com/archives/3093536.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息