TUM CTF Teaser Reverse 10

不算太難的 Reverse ,比較像考 little-endian

建立 table

用 ida 看 發現是用 scanf %llx 讀入 64bit hex 表示的 long long int

輸入的數值會先被 |= 0x8000000000000000;

接著往下看是個 16 次的迴圈,是把輸入的數字每四 bits 取出當 index 加上 local 變數的地圵 找出這個位置後以 byte 為單位加一

把兩個 int64 裡面的 bytes 當 array 用

看 code 比較實在 XD

__int64 v10; // [sp+10h] [bp-18h]@1
  __int64 v11; // [sp+18h] [bp-10h]@1
v10 = 0LL;
  v11 = 0LL;

v4 = 0;
do
{
v5 = 4 * v4++; //從低位址開始 4bits 4bits 取 其實就是 hex 表示數字的一個字 (0~F)
++*((_BYTE *)&v10 + ((v3 & (15LL << v5)) >> v5)); // v10 是 int64 有 8ytes 但 4bits 可以表示到 15 這邊是伏筆
}
while ( v4 != 16 );

check 階段

一樣 16 次的 loop 這次變數(v6)從 0 ~ -15

v6 = 0LL;
  while ( 1 )
  {
    v7 = *((_BYTE *)&v11 + v6 + 7); // +7 常數所以是從 v11 的最後一個 byte 往前看 看到 v10 的最低 byte 為止
    if ( v7 ) // 若不為零 
    {
      if ( v7 != (_BYTE)v6 + 15 || v7 > 8u )
        break;
    }
    --v6;
    if ( v6 == -15 )
    {
      puts(":)");
      system("cat flag.txt");
      return 0;
    }
  }

若 byte 中不為零 會以下圖中數字 check

![](http://i.imgur.com/qVekBBT.jpg)

整理一下 若輸入 0 => |= 0x8000000000000000 => 15 次 index offset = 0, 1次 offset 8

=> v10 的第一的 byte 會變成 15, v11 的第一個 byte = 1

=> check 時希望 v11 的第一個 byte 要是 8 => fail

也就是要湊數字填 table, 為了讓 check 通過必須得數字出現的次數跟數值一樣 ex, 55555, 333, 999999999

然後要 16 位( 64 bits long long int) 因為數直會先被 |= 0x8000000000000000 也就是有一位被限制要 >= 8

以上就是全部條件 那就來填填看 0x8888888844443331 => 通過

存在多組解 符合以上條件都可以 ex 0x8888888855555333 也行