首页
社区
课程
招聘
[原创]看雪 CTF2018 第一题 _iob to getchar or getc?
发表于: 2018-6-16 14:06 1803

[原创]看雪 CTF2018 第一题 _iob to getchar or getc?

HHHso 活跃值
22
2018-6-16 14:06
1803
0x01
签到题,下载,压缩,拖进IDA,查阅"String"
由"success!\n" xref交叉引用到关键业务逻辑,位于main函数处
留意到开头处,复制 "437261636b4d654a757374466f7246756e"提交,错误;
审阅代码逻辑,长度不超过0x11,输入key字符经格式化"%x"转十六进制后再比对上述key,则
通过以下脚本得到输入key
>>> a="437261636b4d654a757374466f7246756e"
>>> for i in xrange(0,a.__len__(),2):
...   print chr(int(a[i:i+2],16)),
...
C r a c k M e J u s t F o r F u n
>>> 'C r a c k M e J u s t F o r F u n'.replace(' ','') 
'CrackMeJustForFun'
复制提交,提示成功。

提炼脚本为  
cmpInnerHexKey = "437261636b4d654a757374466f7246756e"
 b''.join([chr(int( cmpInnerHexKey [i:i+2],16))  for i in xrange(0, cmpInnerHexKey .__len__(),2)])

0x02

如何从汇编逻辑与栈布局揣度作者源代码布局等其它信息?
下述为根据main函数堆栈布局逆推的源码,
通过VC6.0 编译器 cl.exe 的 /O2 优化开关可以得到几乎一模一样的二进制业务逻辑。

//vc98\bin\vcvars32.bat
//kxctf.c
//to compile: cl /O2 kxctf.c
#include <windows.h>
void main(int argc,char* argv){
  char szInnerHexKey[36]="437261636b4d654a757374466f7246756e";
  char szInputHexKey[36];
  char szInputKey[20];
  char szHexKeyCh[2];
  int i;
  char Ch;
  while(1){
    printf("please input your serial:");
    scanf("%s",szInputKey);
    if(strlen(szInputKey)>0x11){
      printf("wrong!\n");
      getchar();
      return;
    }
    for( i=0;i<0x11;i++){
      Ch = szInputKey[i];
      if(Ch==0){
        break;
      }
      sprintf(szHexKeyCh,"%x",Ch);
      strcat(szInputHexKey,szHexKeyCh);
    }
    if(!strcmp(szInputHexKey,szInnerHexKey)){
      printf("success!\n");
    }else{
      printf("wring!\n");
    }
  }
}

对比半F5的结果

int __cdecl main(int argc,const char**argv,const char**envp)

{

  signed int v3;// ebx

  char v4;// al

  int result;// eax

  int v6;// [esp+0h] [ebp-70h]

  int v7;// [esp+0h] [ebp-70h]

  char loc_szHexKeyCh[2];// [esp+12h] [ebp-5Eh]

  char loc_szInputKey[20];// [esp+14h] [ebp-5Ch]

  char loc_szInputHexKey[36];// [esp+28h] [ebp-48h]

  char loc_szInnerHexKey[36];// [esp+4Ch] [ebp-24h]


  strcpy(loc_szInnerHexKey,"437261636b4d654a757374466f7246756e");

  while(1)

  {

    memset(loc_szInputHexKey,0,0x20u);

    *(_WORD*)&loc_szInputHexKey[32]=0;

    loc_szInputHexKey[34]=0;

    printf(aPleaseInputYou,v6);

    scanf(aS,loc_szInputKey);

    if(strlen(loc_szInputKey)>0x11)

      break;

    v3=0;

    do

    {

      v4=loc_szInputKey[v3];

      if(!v4)

        break;

      sprintf(loc_szHexKeyCh,asc_408044,v4);

      strcat(loc_szInputHexKey,loc_szHexKeyCh);

      ++v3;

    }

    while(v3<17);

    if(!strcmp(loc_szInputHexKey,loc_szInnerHexKey))

      printf(aSuccess,v7);

    else

      printf(aWrong,v7);

  }

  printf(aWrong,v7);

  result=Hi__iob_stru_408090._cnt---1;

  if(Hi__iob_stru_408090._cnt<0)

    return _filbuf(&Hi__iob_stru_408090);

  ++Hi__iob_stru_408090._ptr;

  return result;

}


其中

  result=Hi__iob_stru_408090._cnt---1;

  if(Hi__iob_stru_408090._cnt<0)

    return _filbuf(&Hi__iob_stru_408090);

  ++Hi__iob_stru_408090._ptr;

业务逻辑经测试时getchar()的展开。

Hi__iob_stru_408090  结构的引用再运行时环境初始化向量函数 ___initstdio  中引用
.data:0040800C                 dd offset ___initstdio
.data:00408010                 dd offset ___initmbctable

由VC 6.0 d crt源码可知其为  FILE _iob[_IOB_ENTRIES];
开始第一个元素为stdin的定义

/*
 * FILE descriptors; preset for stdin/out/err (note that the __tmpnum field
 * is not initialized)
 */
FILE _iob[_IOB_ENTRIES] = {
        /* _ptr, _cnt, _base,  _flag, _file, _charbuf, _bufsiz */
        /* stdin (_iob[0]) */
        { _bufin, 0, _bufin, _IOREAD | _IOYOURBUF, 0, 0, _INTERNAL_BUFSIZ },
        /* stdout (_iob[1]) */
        { NULL, 0, NULL, _IOWRT, 1, 0, 0 },
        /* stderr (_iob[3]) */
        { NULL, 0, NULL, _IOWRT, 2, 0, 0 },
};

结合getchar的定义,可以相互印证上述逻辑代码为getchar()
#define getc(_stream)     (--(_stream)->_cnt >= 0  ? 0xff & *(_stream)->_ptr++ : _filbuf(_stream))
#define putc(_c,_stream)  (--(_stream)->_cnt >= 0 ? 0xff & (*(_stream)->_ptr++ = (char)(_c)) :  _flsbuf((_c),(_stream)))
#define getchar()         getc(stdin)
#define putchar(_c)       putc((_c),stdout)

全程未曾运行样例程序的情况下做的分析。若运行,测试上述代码估计也能猜测到是getc一类函数。

















[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//