picoCTF - re - OTP Implementation

main函數(shù)邏輯為:

undefined8 main(int argc,undefined8 *argv)

{
  char cVar1;
  byte bVar2;
  int isValid;
  undefined8 ret;
  long in_FS_OFFSET;
  int i;
  int j;
  char buf [100];
  undefined local_84;
  char local_78 [104];
  long canary;
  
  canary = *(long *)(in_FS_OFFSET + 0x28);
  if (argc < 2) {
    printf("USAGE: %s [KEY]\n",*argv);
    ret = 1;
  }
  else {
    strncpy(buf,(char *)argv[1],100);
    local_84 = 0;
    i = 0;
    while( true ) {
      isValid = valid_char((int)buf[i]);
      if (isValid == 0) break;
      if (i == 0) {
        cVar1 = jumble();
        bVar2 = (byte)(cVar1 >> 7) >> 4;
        local_78[0] = (cVar1 + bVar2 & 0xf) - bVar2;
      }
      else {
        cVar1 = jumble();
        bVar2 = (byte)((int)cVar1 + (int)local_78[i + -1] >> 0x37);
        local_78[i] = ((char)((int)cVar1 + (int)local_78[i + -1]) + (bVar2 >> 4) & 0xf) -
                      (bVar2 >> 4);
      }
      i += 1;
    }
    for (j = 0; j < i; j += 1) {
      local_78[j] = local_78[j] + 'a';
    }
    if (i == 100) {
      isValid = strncmp(local_78,
                        "bajbgfapbcclgoejgpakmdilalpomfdlkngkhaljlcpkjgndlgmpdgmnmepfikanepopbapfkdg leilhkfgilgabldofbcaedgfe"
                        ,100);
      if (isValid == 0) {
        puts("You got the key, congrats! Now xor it with the flag!");
        ret = 0;
        goto LAB_001009ea;
      }
    }
    puts("Invalid key!");
    ret = 1;
  }
LAB_001009ea:
  if (canary != *(long *)(in_FS_OFFSET + 0x28)) {
    __stack_chk_fail();
  }
  return ret;
}

從對(duì)輸入加密的邏輯可以得知,加密后數(shù)組中每一元素都會(huì)受前面元素的影響:

local_78[i] = ((char)((int)cVar1 + (int)local_78[i + -1]) + (bVar2 >> 4) & 0xf) -
                      (bVar2 >> 4);

看了很多別人的WP,利用ltrace可以從開頭一字節(jié)一字節(jié)的爆破出密碼。但很麻煩的是對(duì)ltrace和python的subprocess很不熟悉,寫的過程碰了很多次壁,最后的exp為:

import subprocess
import re
from pwn import unhex, xor

flag = "ffadccb05b5892418ff068dd9d42231e8caf8ebb289ea1873f0a474cabe7ce598db77bac9dfef1d7c2b5af3c35bf5844c082"
enc = "bajbgfapbcclgoejgpakmdilalpomfdlkngkhaljlcpkjgndlgmpdgmnmepfikanepopbapfkdgleilhkfgilgabldofbcaedgfe"
key = ["0"] * 100

for i in range(100):
    for j in "0123456789abcdef":
        key[i] = j
        p = subprocess.Popen(["ltrace", "-s", "1000", "./otp", "".join(key)],
                             stdout=subprocess.PIPE,
                             stderr=subprocess.STDOUT)
        brute = re.findall(r"strncmp\(\"(.*?)\".*\)",
                           p.communicate()[0].decode())[0]
        print(brute)
        if brute[i] == enc[i]:
            break
print(xor(unhex("".join(key)), unhex(flag)))

stdout需重定向到管道,否則communicate接收到的數(shù)據(jù)類型為NoneType,而且stderr也應(yīng)重定向到stdout,因?yàn)閘trace中的輸出包含了報(bào)錯(cuò)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容