西普实验吧部分逆向题writeup(一)

本博客已经弃用,我的新博客地址:http://jujuba.me/ 


1. baby Crack

本题难度就像它的名字一样,简单得很。下载程序,先用PEID查一下

西普实验吧部分逆向题writeup(一)_第1张图片

发现没壳,就是C#写的程序


再用IDA打开,往下拉几行即可看到KEY

西普实验吧部分逆向题writeup(一)_第2张图片

KEY: hctf{bABy_CtsvlmE_!}

2.  你会吗

下载完先打开看下:

西普实验吧部分逆向题writeup(一)_第3张图片

PEID查一下:

西普实验吧部分逆向题writeup(一)_第4张图片

别急,用OD打开看看,搜索一下字符串:

 西普实验吧部分逆向题writeup(一)_第5张图片

居然直接就看到了KEY....DUTCTF{We1c0met0DUTCTF}


3. 阿拉丁神灯

PEID 查了一下 又是C#的 那就直接用IDA打开了

这次往下找啊找感觉找不到,直接到左边的函数列表里看看有没有关键的

找到一个叫WindowsApplication1.Form1__Button1_Click 的函数,点进去,又看到KEY了...

西普实验吧部分逆向题writeup(一)_第6张图片

结果又看到了:zhimakaimen@2011

去网站输入之后得到KEY 小明向灯神许愿道~ 灯神啊~ 给我过关的Key吧~ 灯神说道\KEY:UnPack&Crack2011!!


4. 证明自己吧

查壳——没壳——C++编写成的——放入OD调试——搜索字符串——发现成功的字符串附近有跳转函数,改之——在字符串附近下断点——随便输几个数字测试——结果

西普实验吧部分逆向题writeup(一)_第7张图片西普实验吧部分逆向题writeup(一)_第8张图片西普实验吧部分逆向题writeup(一)_第9张图片

看到右下角出现了类似KEY的东西,别急,换个数字试试

西普实验吧部分逆向题writeup(一)_第10张图片

右下角的KEY类似物变化了,由此可知我们需要的KEY应该是临时算出来的,但是这个又不是注册机。我技术不够不能用OD追出码来,只好用IDA来分析具体算法了

打开IDA,先F5反编译MAIN函数:

西普实验吧部分逆向题writeup(一)_第11张图片

我们只看重点,看到gets函数了吧,我们输入的字符串从gets函数进入

看if-else分支的函数调用,if调用的是aGoodTheKey,而else调用的则是aYouDonTGuessIT,很明显,我们要走if分支

去到sub_4011BA函数,F5反编译:


signed int __cdecl sub_401060(const char *a1)
{
  unsigned int v1; // edx@2
  unsigned int v2; // edx@4
  unsigned int v3; // edx@6
  int v5; // [sp+Ch] [bp-10h]@1
  int v6; // [sp+10h] [bp-Ch]@1
  int v7; // [sp+14h] [bp-8h]@1
  __int16 v8; // [sp+18h] [bp-4h]@1
  char v9; // [sp+1Ah] [bp-2h]@1

  v5 = dword_40708C;
  v6 = dword_407090;
  v8 = word_407098;
  v9 = byte_40709A;
  v7 = dword_407094;
  if ( strlen(a1) == strlen((const char *)&v5) )
  {
    v1 = 0;
    if ( strlen(a1) != 0 )
    {
      do
        a1[v1++] ^= 0x20u;
      while ( v1 < strlen(a1) );
    }
    v2 = 0;
    if ( strlen((const char *)&v5) != 0 )
    {
      do
        *((_BYTE *)&v5 + v2++) -= 5;
      while ( v2 < strlen((const char *)&v5) );
    }
    v3 = 0;
    if ( strlen((const char *)&v5) == 0 )
      return 1;
    while ( *((_BYTE *)&v5 + v3 + a1 - (const char *)&v5) == *((_BYTE *)&v5 + v3) )
    {
      ++v3;
      if ( v3 >= strlen((const char *)&v5) )
        return 1;
    }
  }
  return 0;
}

我们先看第一段算法:

if ( strlen(a1) == strlen((const char *)&v5) )
  {
    v1 = 0;
    if ( strlen(a1) != 0 )
    {
      do
        a1[v1++] ^= 0x20u;
      while ( v1 < strlen(a1) );
    }

看到我们传进来的字符串叫做a1,假如a1的长度等于v5的长度,则开始逐个元素做异或运算,和20异或
我们点进40708C地址看一看v5:

西普实验吧部分逆向题writeup(一)_第12张图片

在此要注意的是v5存储的是地址,即需要比较的字符串的首地址,整个字符串应为 68571948 506e5878 546a1958 5e06H


再看第二段:

v2 = 0;
    if ( strlen((const char *)&v5) != 0 )
    {
      do
        *((_BYTE *)&v5 + v2++) -= 5;
      while ( v2 < strlen((const char *)&v5) );
    }
v5中的每个字节中存储的值-5


最后一段则是:

v3 = 0;
    if ( strlen((const char *)&v5) == 0 )
      return 1;
    while ( *((_BYTE *)&v5 + v3 + a1 - (const char *)&v5) == *((_BYTE *)&v5 + v3) )
   {
      ++v3;
     if ( v3 >= strlen((const char *)&v5) )
        return 1;
    }

可以看出这一段是在比较逐个a1和v5中的元素,while的循环条件前半部分有代码混淆,其实那一堆就相当于*(v3+a1)


现在我们的问题简化为:

我们输入了一段字符串,假设叫code

encode=code^20

当encode=str-5时条件就成立,此时的code就是我们想要的KEY

我们还需要知道的就是一个数连续对另一个数求异或两个,此时得到的数不变

所以我们只要把(str-5)^20就能得到key了


C++代码如下:

#include 
using namespace std;
int main(void)
{
	string code="\x68\x57\x19\x48\x50\x6e\x58\x78\x54\x6a\x19\x58\x5e\x06";
	for(int i=0;i<14;i++)
		code[i]=(code[i]-5)^0x20;
	cout<
输出结果:


顺便贴个Python代码:

code=(0x68,0x57,0x19,0x48,0x50,0x6e,0x58,0x78,0x54,0x6a,0x19,0x58,0x5e,0x06)
for i in code:
    i=(i-5)^0x20
    print chr(i)

西普实验吧部分逆向题writeup(一)_第13张图片

KEY:Cr4ckIsSoE4sy!






你可能感兴趣的:(逆向之路)