ISCC 2016 逆向部分 writeup

Posted GlodsNow

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ISCC 2016 逆向部分 writeup相关的知识,希望对你有一定的参考价值。

ISCC2016 逆向部分

by GoldsNow

做了这套题目感觉涨了不少的姿势。。渣渣就只能够用渣渣的方法

题目下载

Help me

描述:I’ve got a difficult task and I can’t solve it. I need your help!

思路:爆破

ELF64位的程序,直接在IDA中打开,可以看出来思路应该是比较清晰
先点进去main函数来进行分析。
技术分享

for ( i = 0; i <= 15; ++i )
{
    if ( !(v11 & 1) )
      ++v5;
    v11 >>= 1;
} 

先对这个一段代码进行分析,经过位运算,来判断二进制数字有多少个 0
很明显 这里只需要三个 0

这里的MD5是个比较坑的地方,C语言并没有自带的库, 也不知道它到底进行的是什么。 只知道他是与 unk_6020A0 来比较的 有尝试 对这个地址的数据进行 MD5的解密,可惜最终是失败了的。

换一个思路,我们可以看到这里的 word_602080 经过了异或运算 然后 byte_6020C0 减去 这个的值然后输出最终的flag 所以可以从这个角度来解决题目, 这里面值有 V10也就是输入的那一个数字是不知道的, 可以通过暴力破解来实现。
我在做题目的时候用了C语言来判断, 判断第五个字母是不是‘{’

附上我的c程序可以参考一下。
unsigned char a[]={0x34,0x12,0x78,0x56,0xBC,0x9A,0xFF,0xED,0xEF,0xBE,0x7F,0x22,0xC3,0x90,0x76,0x82,0xAD,0x99,0x2E,0x14,0x7C,0x80};
unsigned char b[]={0x22,0x3F,0xD8,0xEB,0xCC,0xD2,0x42,0x87,0x61,0x75,0x01,0x09,0x27,0xF9,0xDC,0xE8,0x16,0xFC,0x5F,0x89,0xB3,0xFD};
__int16 c[6]={0x3412,0x7856,0xbc9a,0xffed,0xefbe,0x7f22};
__int16 d[6];
__int16 x1=0,x2=0xffff,x=0;
for(int i=0;i<=15;i++)                         // 三重for循环将 v10的可能性都列出来了 
    for(int j=i+1;j<=15;j++)
        for(int m=j+1;m<=15;m++)
        {
            x2==0xffff;
            x1=(__int16)(pow(2,i)+pow(2,j)+pow(2,m));  
            x=x2-x1;                    //这三行是为了得到V10的可以理解一下   

            for(int n=0;n<=5;n++)     
            {
                d[n]=c[n]^x;
                a[2*n]=d[n]>>8;
                a[2*n+1]=( __int8) d[n];
            }
            if(b[4]-a[4]==‘{‘) //如果是‘{‘就输出 可能的flag 
            {
                printf("%x ",x);
                for(int i=0;i<22;i++)  
                    printf("%c",b[i]-a[i]);
                printf("\n");
            }
        }

破解加密软件

描述:我方截获了敌方的一款加密程序和一段密文,尝试通过对此程序进行分析实现对密文的解密,解密后明文的32位小写MD5值作为flag提交。

思路:扣出程序中所包含的一个加密解密系统,得到密钥 解密

吾爱破解对于这个题目也有比较详细的解题过程 链接

技术分享

通过OD载入然后搜索里面的字符串可以发现 程序有两个功能,一个就是原题所给的 输入字符串就加密,其实里面还有一个程序就是 通过给与密钥就能够加密与解密

通过修改跳转,或者修改 call 的内容等等其他 方法能够让程序运行到那一段 这样就好办了。但是 还不知道密钥是什么。
想法是密钥肯定会在 初始的加密程序中引用

对程序进行单步跟踪。一步一步运行 到达一定地方的时候堆栈中就出现了如下可惜的八位数字,并且这个不会随着你的输入而改变数字,猜测其为密钥

技术分享
果然没错 一下子就出来了

这里有一个地方就是 直接用OD跑出来的值会有一个空格多出来也不知道是为什么。

 菜鸟的逆袭

描述:”小明是个游戏新手,一天他闲得无聊去找基友打L4D2,基友嫌他太菜,不愿带他,无奈小明百般纠缠,便给了他一个程序,并且告诉他:“如果你能得到正确答案,我就把我毕生混野绝学传授给你。”聪明的你能帮助小明得到正确的答案吗?
测试环境:干净的WinXP SP3”

找不到动态调试的软件。只能够静态分析,用IDA打开。

技术分享

可以通过提示 推断出来 这里有两个词,分别是DEAD和BEEF
正好属于A-F 因为是A-F 属于0-F的范围 都符合16进制的值。所以上面的V9就是0xdeadbeef或者说0xDEADBEEF

通过将dword_10F80-dword_10F90与V9异或输出,能够得到 一串看起来很像flag的值但是 要靠程序接下来分析 将字符串进行了转化

orPh0fh!:hlghnoCgalF

技术分享 技术分享
这样转化一下就出来了,,是不是很简单,,,但是要去想到却很难。。

矛盾

描述:To be or not to be, that is the question.

思路 去除TLS,暴力

参考资料 http://www.2cto.com/Article/201303/197705.html

IDA载入
技术分享

找到TLScallback 在010中打开它用00填充此部分 保存文件就能够进入程序的主函数部分了,但是还是不能够得到flag 有点小郁闷

通过查看字符串来寻找有没有弹出窗口,运气不错发现一个弹出窗口。
并且在上面也出现了flag的字样。

技术分享

函数的上有几个 sub_4385FF 推测他用的就是memset 将目标的地址段 值置零。所以这里就会使最终的flag

最后处理 的是直接打开OD跳转到相关的语段 跑一下就出来了。

 Anti

描述:Every technique has its anti.

这个题目就是 反调试,,绕过dll文件中的对调试器和模拟器的检测。。

操作方法,具体就不介绍了,就是在OD中 一步一步,对于有些 call 直接就nop掉 一些明显要推出的函数就强制跳转或者也nop了
进入主程序之后,难度就会明显下降

技术分享

很容易就能够找到主要的那个对比的地址, 最后有一段看起来很复杂的加密方法,,,,分析半天没分析出来,后来一看就32位的,,就想到了可能是用了MD5加密方法,,最终在XMD5 一下子就出来flag 了。

GoGoGo

描述:Mission is a go.

这个题目用了GO语言。问了很多人,都说是用动态分析做出来了,但是我最后是通过静态分析,很容易就做出来了。

IDA的分析是非常规的。 只能靠猜

 v38 = "Please input : ";
  v39 = off_4DC4C0[1];
  v40 = 0LL;
  v41 = 0LL;
  if ( &v30 == -88 )
    LODWORD(v40) = 0;
  v42 = &v40;
  v43 = 1;
  v44 = 1;
  v30 = &unk_4A10A0;
  v31 = &v38;
  sub_41FA10(&v42, a2, a3, v3);
  v4 = v42;
  v5 = v42;
  *v42 = v32;
  ++v5;
  *v5 = v33;
  ++v5;
  v30 = v4;
  v31 = v43;
  v32 = v44;
  sub_42C510(v5, &v34, v6, v7, v8, v9);
  sub_400C00(v5, &v34);
  v36 = v30;
  v37 = v31;
  v32 = &unk_4D73F0;
  v33 = *(&off_4D73E0 + 1);
  v10 = &off_4D73E0 + 2;
  sub_446A70(&v34, (&off_4D73E0 + 2), v11, v30, v12, v13);
  v16 = v34;
  v36 = v34;
  v37 = v35;
  if ( v35 != 38 || (v30 = v34, v31 = 38, sub_400CB0(&v34, v10, v14, v34, v15), v32 != 1) )
  {
    v38 = "Wrong!!!";
    v39 = off_4DCCE0[1];
    v40 = 0LL;
    v41 = 0LL;
    if ( &v30 == -88 )
      LODWORD(v40) = 0;
    v42 = &v40;
    v43 = 1;
    v44 = 1;
    v30 = &unk_4A10A0;
    v31 = &v38;
    sub_41FA10(&v42, v10, v14, v16);
    v24 = v42;
    v25 = v42;
    *v42 = v32;
    ++v25;
    *v25 = v33;
    v30 = v24;
    v31 = v43;
    v32 = v44;
    result = sub_42C510((v25 + 1), &v34, v26, v27, v28, v29);
  }
  else
  {
    v38 = "Congratz!!";
    v39 = off_4DB7A0[1];
    v40 = 0LL;
    v41 = 0LL;
    if ( &v30 == -88 )
      LODWORD(v40) = 0;
    v42 = &v40;
    v43 = 1;
    v44 = 1;
    v30 = &unk_4A10A0;
    v31 = &v38;
    sub_41FA10(&v42, v10, v14, v16);
    v17 = v42;
    v18 = v42;
    *v42 = v32;
    ++v18;
    *v18 = v33;
    v30 = v17;
    v31 = v43;
    v32 = v44;
    result = sub_42C510((v18 + 1), &v34, v19, v20, v21, v22);
  }

截图太累 直接把代码复制了,,通过对比 可以看出 这个 ‘sub_42C510’ 才是输出的结束语句
input 那边还需要一个读取字符的语句 就猜测是 ‘sub_446A70’ 这语段是输出语段。

主要起作用的当然是 if语句里的那个 sub_400CB0 了

技术分享

这里有一个 字符转化和一个内存中的数据很可疑,,刚开始以为是输入的语句经过处理变成这样,但是实际上我错了。是这个内存中的 数据 经过这个处理会出现一段base64加密过的数据。。

附上代码
int b[52]={0xA5,0xD6,0x87,0x86,0xA5,0x33,0x37,0x03,0xE4,0x75,0xE4,0xB6,0x95,0xA7,0xC6,0xD6,0xE4,0x44,0x94,0x53,0xE4,0xA6,0xB6,0x53,0xD4,0x23,0xD4,0x77,0xD4,0xA7,0x46,0xB6,0xA5,0x74,0x55,0x13,0xD4,0xA6,0x36,0x87,0x95,0x75,0x55,0x43,0x95,0xA6,0x15,0x03,0x95,0x33,0x03,0xD3}; 
for(int j=0;j<52;j++)
{
    printf("%c",(16*b[j]|b[j]>>4));
}

就是这么简单,,然后将这个进过base64解密一下就出来了 我也觉的很意外。














以上是关于ISCC 2016 逆向部分 writeup的主要内容,如果未能解决你的问题,请参考以下文章

ISCC 2020 Writeup

ISCC 2020 Writeup

ISCC 2017 Web writeup

iscc2018-Reverse-writeup

ISCC 2018线上赛 writeup

ISCC2016 mobile