无壳,IDA打开可以直接进入main函数:

第12行调用VirtualProtect函数更改了offset encrypt处的访问保护权限

BOOL VirtualProtect(LPVOID lpAddress,SIZE_T dwSize,DWORD  flNewProtect,PDWORD lpflOldProtect
);

参见:https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection-constants

该处数据为0x4:PAGE_READWRITE

Enables read-only or read/write access to the committed region of pages. If Data Execution Prevention is enabled, attempting to execute code in the committed region results in an access violation.

简单来说就是让这块数据能够被读写了(通常text段中只能拥有读/写中的一种)

继续往下读,发现输入值应该符合 24字节 的长度,然后遇到wrong 和 omg这两个函数

char *__cdecl wrong(char *a1)
{char *result; // eaxint i; // [esp+Ch] [ebp-4h]for ( i = 0; i <= 23; ++i ){result = &a1[i];if ( (i & 1) != 0 )a1[i] -= i;elsea1[i] ^= i;}return result;
}
int __cdecl omg(char *a1)
{int result; // eaxint v2[24]; // [esp+18h] [ebp-80h] BYREFint i; // [esp+78h] [ebp-20h]int v4; // [esp+7Ch] [ebp-1Ch]v4 = 1;qmemcpy(v2, &unk_4030C0, sizeof(v2));for ( i = 0; i <= 23; ++i ){if ( a1[i] != v2[i] )v4 = 0;}if ( v4 == 1 )result = puts("hahahaha_do_you_find_me?");elseresult = puts("wrong ~~ But seems a little program");return result;
}

wrong对输入值进行了一些加减或异或处理,然后将结果在omg中同unk_4030C0处数据进行对比;wrong的逆算法容易实现,照抄就行了

(现在才知道能够通过导出窗口快捷的提取出数据,一直以来的手抄实在是太笨了)

 unsigned int k[24] = { 0x66,0x6b,0x63,0x64,0x7f,0x61,0x67,0x64,0x3b,0x56,0x6b,0x61,0x7b,0x26,0x3b,0x50,0x63,0x5f,0x4d,0x5a,0x71,0xc,0x37,0x66 };for (int i = 0;i < 24; i++){if ((i & 1) != 0){k[i] += i;}else{k[i] ^= i;}cout << (char)k[i];}cout << endl;

得到结果flag{fak3_alw35_sp_me!!},提交发现错误;由于往下还有关键的encrypt段没分析,所以不用太怀疑flag是否算错,可以大胆的将它当作一个假的flag

再往下读for循环,发现它对offset encrypt进行了异或,判断其为代码段解密,可以用动调转到这个地方

IDA没能及时更新,需要我们手动修正为函数

选中00401500~0040152F,将其标为代码(Force)

然后在00401502处创建函数,即可得到合适的结果

// positive sp value has been detected, the output may be wrong!
void __usercall __noreturn sub_401502(int a1@<ebp>)
{unsigned __int32 v1; // eaxv1 = __indword(0x57u);*(_DWORD *)(a1 - 32) = 1;qmemcpy((void *)(a1 - 108), &unk_403040, 0x4Cu);for ( *(_DWORD *)(a1 - 28) = 0; *(int *)(a1 - 28) <= 18; ++*(_DWORD *)(a1 - 28) ){if ( (char)(*(_BYTE *)(*(_DWORD *)(a1 - 28) + *(_DWORD *)(a1 + 8)) ^ Buffer[*(_DWORD *)(a1 - 28)]) != *(_DWORD *)(a1 + 4 * *(_DWORD *)(a1 - 28) - 108) ){puts("wrong ~");*(_DWORD *)(a1 - 32) = 0;exit(0);}}if ( *(_DWORD *)(a1 - 32) == 1 )puts("come here");
}

IDA分析得到的代码并不是那么易读,显然,它将一些索引给翻译错了,但并非无法理解的程度

首先,提取unk_403040处的数据放入(a1-108)处,以及循环中用到的Buffer

 char Buffer[] = "hahahaha_do_you_find_me?";unsigned int unk_403040[19] = {0x0E,0x0D ,0x09 ,0x06 ,0x13 ,0x05 ,0x58 ,0x56 ,0x3E ,0x06 ,0x0C ,0x3C ,0x1F ,0x57 ,0x14 ,0x6B ,0x57 ,0x59 ,0x0D };

*(a1-28)实际上是一个索引,指示了这个循环会执行19次;而(*(a1 - 28) + *(a1 + 8))相当于输入值指针加上一个偏移,其内容就是我们的输入值

这个输入值和Buffer异或后的结果应该等于(a1 - 108)的内容,也就是unk_403040处的数据,同样也容易写出解密代码

 char key1[] = "hahahaha_do_you_find_me?";unsigned int f[19] = {0x0E,0x0D ,0x09 ,0x06 ,0x13 ,0x05 ,0x58 ,0x56 ,0x3E ,0x06 ,0x0C ,0x3C ,0x1F ,0x57 ,0x14 ,0x6B ,0x57 ,0x59 ,0x0D };for (int i = 0; i < 19; i++){f[i] ^= key1[i];cout << (char)f[i];}cout << endl;

得到flag{d07abccf8a410c

我们知道,flag应有24字节,但for循环只有19次,也就是缺少了5个字符;由于encrypt函数已经读完了,所以我们需要的结果应该在最后一个函数中,也就是finally函数

将40159A~40159D处的数据全都转为代码,并将函数改为Undefine

重新在40159A处创建函数,得到新函数finally:

int __cdecl finally(char *a1)
{unsigned int v1; // eaxint result; // eaxchar v3[9]; // [esp+13h] [ebp-15h] BYREFint v4; // [esp+1Ch] [ebp-Ch]strcpy(v3, "%tp&:");v1 = time(0);srand(v1);v4 = rand() % 100;if ( (v3[*&v3[5]] != a1[*&v3[5]]) == v4 )result = puts("Really??? Did you find it?OMG!!!");elseresult = puts("I hide the last part, you will not succeed!!!");return result;
}

time(0)用以获取当前时间,第10行将其作为种子,第11行获取随机数;大概率我们是难以获取到出题人得到的种子的,因此,这个随机数若是必要的,应该只能通过预测得出

以及下面的if判断条件过于难以理解,不妨试着用OD去动调一下吧(个人觉得OD的动调会更好用一些,也好在这个函数没有被加密,OD还是能分析出来的,否则只能用IDA动调了,虽然没什么差别......)

即便用OD动调也仍然不是很容易能够读懂其意义

关键的比较在401617处,如果相等的话,就说明flag输对了

大致就是取flag的第几位同“%tp&:"几位,相等即可;并且这正好是5个字节,很可能就是剩下的flag

但汇编代码中似乎也同样没有相应的加密过程,只能靠猜测它没有被复杂的加密

通过前半段的flag猜测最后一个字符应该为‘}’,将其与“%tp&:”的最后一个异或后得到 71,并由此得到最后结果

 char key2[] = "%tp&:";int v5 = '}' ^ key2[4];for (int i = 0; i < 5; i++){cout << (char)(key2[i] ^ v5);}
//flag{d07abccf8a410cb37a}

我也试着将这个提交成功的flag输入进去,但它仍然不会输出成功的标识,可能是出题人的一点“恶意”吧......最后要靠猜测来得到结果,说实在的,有点难以释然,总觉得是不是自己看漏了什么重要内容......

[BUUCTF][网鼎杯 2020 青龙组]jocker 分析与记录相关推荐

  1. Buuctf [网鼎杯 2020 青龙组]jocker 题解

    目录 一.主函数逻辑 二.wrong函数和omg函数--假flag 1.wrong函数 2.omg函数 3.假flag 三.encrypt和finally函数--真flag 1.打开sp指针偏移显示 ...

  2. re -25 buuctf [网鼎杯 2020 青龙组]jocker

    [网鼎杯 2020 青龙组]jocker 前话:ida7.6设置栏内没有general,可以通过ctrl+shift+p打开命令面板,搜索option打开设置选项,于Disassembly设置堆栈显示 ...

  3. BUUCTF Reverse/[网鼎杯 2020 青龙组]jocker

    BUUCTF Reverse/[网鼎杯 2020 青龙组]jocker 先看下文件信息,没有加壳,32位程序 运行一下,又是一道字符串比较的题目 用IDA32位打开,分析一下 // positive ...

  4. [网鼎杯 2020 青龙组]jocker

    [网鼎杯 2020 青龙组]jocker SMC(self-Modifying Code): 自修改代码,程序在执行某段代码的过程中会对程序的代码进行修改,只有在修改后的代码才是可汇编,可执行的.在程 ...

  5. Buuctf[网鼎杯 2020 青龙组]AreUSerialz

    [网鼎杯 2020 青龙组]AreUSerialz 打开题目仔细阅读源码 <?phpinclude("flag.php"); highlight_file(__FILE__) ...

  6. [BUUCTF]Reverse——[网鼎杯 2020 青龙组]jocker

    网上大部分是动调,我尝试IDC解一下, 无壳,32位,放入IDApro,查看main函数 查看wrong和str函数,借出假的flag a=[0x66,0x6B,0x63,0x64,0x7F,0x61 ...

  7. buuctf刷题记录21 [网鼎杯 2020 青龙组]jocker

    今天挑战一下,结果最后还是看了别人的wp才写出来的 无壳,ida查看发现不能f5,原因堆栈不平衡 进行栈指针修改 修改出错的地方的栈指针偏移,快捷键alt+k,值改为0 然后就能f5了, 逻辑也不难, ...

  8. BUUCTF·[网鼎杯 2020 青龙组]boom·WP

    BUUCTF在线评测 (buuoj.cn) 附件 是一个可运行的文件 回车出现: 分析 猜测是C编写的,拉到编译器,发现提示是二进制文件 那就用010Editor打开 查找了一下flag,这不就是跟附 ...

  9. [网鼎杯 2020 青龙组]jocker(详解)

    首先我们查看一下信息,32位程序,无壳: 然后用IDA打开,提示// positive sp value has been detected, the output may be wrong! 出现了 ...

最新文章

  1. 《分布式服务架构:原理、设计与实战》第二章彻底解决分布式系统一致性的问题...
  2. 装运点确认失败的排查
  3. 2020全国大学生数学建模竞赛【论文格式、时间节点及作品提交要求、竞赛题目下载、评分要点】【微信公众号:校苑数模】
  4. java 数据截断_java – 数据截断:第1行的列’标志’的数据太长
  5. CF611F. New Year and Cleaning
  6. linux shell if -a 到-z参数含义
  7. 品质标签分几种颜色_常见标签种类分析
  8. Docker学习总结(28)——Docker 容器健康检查机制
  9. git学习(三)分支管理
  10. Linux kernel中网络设备的管理
  11. Navicat安装问题及解决办法
  12. layabox flash转html5,FlashBuilder中第一个H5程序“Hello Layabox”
  13. python 生成 exe
  14. 好玩好用的网站,不能错过!
  15. ios WKWebView之视频无法播放
  16. 【数字图像处理】【Matlab】【实验一】图像处理基本操作
  17. 疯狂的世界,疯狂的人!
  18. 中国尼龙搭扣市场趋势报告、技术动态创新及市场预测
  19. 小米手机安装推特后频繁闪退
  20. 在Ubuntu PHP中基于wxsqlite3扩展使用加密的Sqlite数据库

热门文章

  1. 新一批电子商务解决方案和企业管理应用加入 VM Depot 中国站点
  2. TP-LINK路由器端口映射详解
  3. 自然语言处理与应用化学专业的关系
  4. 怎么把两个pdf合并成一个?三种合并方法任你选择
  5. 2006年最经典精品语录!!
  6. 国外lead怎么快速入门
  7. R TALK | 旷视孙剑:如何打造云、端、芯上的视觉计算
  8. 身体训练 (概率论)
  9. 删除pdf复制过来文字的回车或空格
  10. 深入理解之overflow属性(第五期)