7.24 兩道二進制題目練習的總結

1.興趣是最好的老師
首先我們把根據PE文件的格式知道這個文件本身有錯誤,所以不能在IDA中打開,我們先把它在010Editor.exe中修改一下,我們把PE頭改爲50 45 00 00,然後就把它拉入IDA中,然後打開,找到有程序的開始進行分析。

__int64 main_0()
{
  int v0; // edx
  __int64 v1; // ST00_8
  int v3; // [esp+0h] [ebp-1A0h]
  const char **v4; // [esp+4h] [ebp-19Ch]
  const char **v5; // [esp+8h] [ebp-198h]
  int v6; // [esp+Ch] [ebp-194h]
  int i; // [esp+D4h] [ebp-CCh]
  int v8; // [esp+E0h] [ebp-C0h]
  int v9; // [esp+ECh] [ebp-B4h]
  int v10; // [esp+F0h] [ebp-B0h]
  int v11; // [esp+F4h] [ebp-ACh]
  int v12; // [esp+F8h] [ebp-A8h]
  int v13; // [esp+FCh] [ebp-A4h]
  int v14; // [esp+100h] [ebp-A0h]
  int v15; // [esp+104h] [ebp-9Ch]
  int v16; // [esp+108h] [ebp-98h]
  int v17; // [esp+10Ch] [ebp-94h]
  int v18; // [esp+110h] [ebp-90h]
  int v19; // [esp+114h] [ebp-8Ch]
  int v20; // [esp+118h] [ebp-88h]
  int v21; // [esp+11Ch] [ebp-84h]
  int v22; // [esp+120h] [ebp-80h]
  int v23; // [esp+124h] [ebp-7Ch]
  int v24; // [esp+128h] [ebp-78h]
  int v25; // [esp+12Ch] [ebp-74h]
  int v26; // [esp+130h] [ebp-70h]
  int v27; // [esp+134h] [ebp-6Ch]
  int v28; // [esp+138h] [ebp-68h]
  int v29; // [esp+13Ch] [ebp-64h]
  int v30; // [esp+140h] [ebp-60h]
  char v31; // [esp+14Fh] [ebp-51h]
  char v32[17]; // [esp+178h] [ebp-28h]
  char v33; // [esp+189h] [ebp-17h]
  char v34; // [esp+18Ah] [ebp-16h]
  char v35; // [esp+18Bh] [ebp-15h]
  char v36; // [esp+18Ch] [ebp-14h]
  char v37; // [esp+18Dh] [ebp-13h]

  v31 = 0;
  v9 = 1;
  v10 = 4;
  v11 = 14;
  v12 = 10;
  v13 = 5;
  v14 = 36;
  v15 = 23;
  v16 = 42;
  v17 = 13;
  v18 = 19;
  v19 = 28;
  v20 = 13;
  v21 = 27;
  v22 = 39;
  v23 = 48;
  v24 = 41;
  v25 = 42;
  v26 = 26;
  v27 = 20;
  v28 = 59;
  v29 = 4;
  v30 = 0;
  printf("please enter flag:");
  while ( 1 )
  {
    v6 = getch();
    v32[v31] = v6;
    if ( !(_BYTE)v6 || v32[v31] == 13 )
      break;
    if ( v32[v31] == 8 )
    {
      printf("\b\b");
      --v31;
    }
    else
    {
      printf("%c", v32[v31++]);
    }
  }
  v8 = 0;
  for ( i = 0; i < 17; ++i )
  {
    if ( v32[i] != byte_415768[*(&v9 + i)] )
      v8 = 1;
  }
  if ( v33 != 49 || v34 != 48 || v35 != 50 || v36 != 52 || v37 != 125 )
    v8 = 1;
  v32[v31] = 0;
  printf("\r\n");
  if ( v8 )
  {
    printf("wrong\n");
    main(v3, v4, v5);
  }
  else
  {
    printf("success\n");
  }
  system("pause");
  HIDWORD(v1) = v0;
  LODWORD(v1) = 0;
  return v1;
}

分析函數可以得知,只有當變量V8=0時,flag纔是正確的,所以我們需要滿足v8=0成立的條件,所以通過如下對於各變量的地址值,通過對各變量地址值作爲所給字符串形成的字符數組的數組下標分別按計算的順序取出,即可得到答案。

 for ( i = 0; i < 17; ++i )
  {
    if ( v32[i] != byte_415768[*(&v9 + i)] )
      v8 = 1;
  }
  if ( v33 != 49 || v34 != 48 || v35 != 50 || v36 != 52 || v37 != 125 )
    v8 = 1;

這個循環判斷了長度爲17的數組v32中的每個字符是否與數組byte_415768[]中的對應字符是否相等。在IDA PRO中雙擊byte_415768[],會跳到其定義處,
這裏寫圖片描述最後跟的是個0,一般用於表示字符串結束(與c代碼中一致)
!!!!!!
語句byte_415768[(&v9+ i)]中&v9表示取變量v9的地址,然後假設遊標量i,再用運算符找對應地址的值,i從0變到17,那麼byte_41576[]中的序號依次爲v9,v10,v11,….v25,共計17個變量的值,而byte_415768[1]=’K’,byte_415768[4]=’E,byte_415768[14]=‘Y’,byte_415768[10]={……
最終可以得到KEY{e2s6ry3r5s8f6這17個字符,這是答案的上半部分,然後觀察代碼中if ( v33 != 49 || v34 != 48 || v35 != 50 || v36 != 52 || v37 != 125 )
v8 = 1

下半部分由v8的第二部分賦值代碼來獲得,這裏面有多個變量的或非判斷,即v33,v34,v35,v36不等於49,48,50,52,125時,v3就爲1。從終端錄入的一般是用ascii碼存放,所以查 49,48,50,52,125對應的ASCII碼爲’1’,’0’,’2’,’4’,’}’,顯然是字符串“1024}”。
用Python編寫腳本爲:

a='sKfxEeft}f{gyrYgthtyhifsjei53UUrrr_t2cdsef66246087138\0087138'
b=[1,4,14,10,5,36,23,42,13,19,28,13,27,39,48,41,42,26,20,59,4,0]
for i in range(17):
    print(a[b[i]],end='')
print('1024}'

結果爲:KEY{e2s6ry3r5s8f61024}
2.ctf2,please input your key
使用IDA打開這個題後,找到程序的代碼如下:

nt __cdecl main()
{
  char s; // [esp+10h] [ebp-110h]

  printf("Input flag:");
  sub_80485A0(&s, 0x100u);
  if ( (unsigned __int8)sub_8048630(&s) )
    puts("Flag is right.");
  else
    puts("Flag is wrong.");
  return 0;
}

由上得知,如果我們滿足unsigned __int8)sub_8048630(&s)這個條件,我們就會得到正確的flag,我們點開sub_8048630,得到下列代碼

int __cdecl sub_8048630(char *s)
{
  size_t v1; // eax
  int v3; // edx

  if ( s )
  {
    v1 = strlen(s);#strlen()函數作用爲獲取字符串的長度
    if ( v1 )
    {
      if ( v1 == 29 )
      {
        v3 = 0;
        while ( s[v3] == byte_8049AE0[(unsigned __int8)((unsigned __int8)byte_8049B15[v3] / 3u - 2)] )
        {
          if ( ++v3 == 29 )
            return 1;
        }
      }
    }
  }
  return 0;
}

分析上述代碼可得,我們輸入的v1的長度要等於29,這時v3初始值爲0,程序可以向下運行,當v3=29的時候,我們就會得到我們想要的flag,接着我們要分析一下

while ( s[v3] == byte_8049AE0[(unsigned __int8)((unsigned __int8)byte_8049B15[v3] / 3u - 2)] )

這段代碼的含義,我們找到s[v3]要等於後面的,程序纔可以繼續向下面執行,首先,我們點開byte_8049B15這個
這裏寫圖片描述
看到了這一列16進制的數,然後我們選定這個區域按快捷鍵shift+E得到這些16進制數,
{
0x48, 0x5D, 0x8D, 0x24, 0x84, 0x27, 0x99, 0x9F, 0x54, 0x18,
0x1E, 0x69, 0x7E, 0x33, 0x15, 0x72, 0x8D, 0x33, 0x24, 0x63,
0x21, 0x54, 0x0C, 0x78, 0x78, 0x78, 0x78, 0x78, 0x1B
}
接着我們打開byte_8049AE0這個
這裏寫圖片描述
得到了一串字符串’lk2j9Gh}AgfY4ds-a6QW1#k5ER_T[cvLbV7nOm3ZeX{CMt8SZo]U’
s[v3] == byte_8049AE0[(unsigned __int8)((unsigned __int8)byte_8049B15[v3] / 3u - 2)] 表示s[i]等於將那些16進制除以3再減去2,然後取整型,然後再對應字符串取相應位置的字符,
編寫python腳本如下所示:

a=[0x48, 0x5D, 0x8D, 0x24, 0x84, 0x27, 0x99, 0x9F, 0x54, 0x18, 
  0x1E, 0x69, 0x7E, 0x33, 0x15, 0x72, 0x8D, 0x33, 0x24, 0x63, 
  0x21, 0x54, 0x0C, 0x78, 0x78, 0x78, 0x78, 0x78, 0x1B]
b=[]
for i in range(len(a)):
    b.append(int(a[i]/3-2))
s='lk2j9Gh}AgfY4ds-a6QW1#k5ER_T[cvLbV7nOm3ZeX{CMt8SZo]U'
flag=''
for j in range(len(b)):
    flag+=s[b[j]]
print(flag)    

得到的結果爲:kctf{YoU_hAVe-GOt-fLg_233333}
. append() 方法向列表的尾部添加一個新的元素,只接受一個參數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章