攻防世界666

题目地址: 666

将附件下载到本地后,直接拖进 IDA 进行分析,点击进入 main 函数。

 ; =============== S U B R O U T I N E =======================================
 ; Attributes: bp-based frame

 ; int __cdecl main(int argc, const char **argv, const char **envp)
                 public main
 main            proc near               ; DATA XREF: _start+1D↑o

 s               = byte ptr -1E0h		   ; s[480]
 var_F0          = byte ptr -0F0h		   ; var_fo[240],存放scanf输入参数

 ; __unwind {
            push    rbp
            mov     rbp, rsp
            sub     rsp, 1E0h
            lea     rax, [rbp+s]
            mov     edx, 1Eh        ; n
            mov     esi, 0          ; c
            mov     rdi, rax        ; s
            call    _memset			; memset(s, 0, 0x1EuLL);
            
            lea     rdi, format     ; "Please Input Key: "
            mov     eax, 0
            call    _printf
            
            lea     rax, [rbp+var_F0]
            mov     rsi, rax
            lea     rdi, aS         ; "%s"
            mov     eax, 0
            call    ___isoc99_scanf
            
            lea     rdx, [rbp+s]
            lea     rax, [rbp+var_F0]
            mov     rsi, rdx
            mov     rdi, rax
            call    encode			;关键函数,这里对输入字符进行了加密
            
            lea     rax, [rbp+var_F0]
			mov     rdi, rax        ; s
			call    _strlen
			mov     rdx, rax
			mov     eax, cs:key
			cdqe
			cmp     rdx, rax
			jnz     short loc_138D
			lea     rax, [rbp+s]
			lea     rsi, enflag     ; "izwhroz\"\"w\"v.K\".Ni"
			mov     rdi, rax        ; s1
			call    _strcmp
			test    eax, eax
			jnz     short loc_1381
			lea     rdi, aYouAreRight ; "You are Right"
			call    _puts
			jmp     short loc_138D
 ; ---------------------------------------------------------------------------

 loc_1381:                               ; CODE XREF: main+A0↑j
			lea     rdi, aFlagThis1sF4ck ; "flag{This_1s_f4cker_flag}"
            call    _puts

 loc_138D:                               ; CODE XREF: main+86↑j
                                         ; main+AE↑j
            mov     eax, 0
            leave
            retn
; } // starts at 12D1
 main       endp

按下 F5 ,反汇编,这下就清楚程序运行逻辑了,程序对输入字符进行字符编码,然后与 enflag(“izwhroz""w"v.K".Ni”)进行比较。。。

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s[240]; // [rsp+0h] [rbp-1E0h] BYREF
  char v5[240]; // [rsp+F0h] [rbp-F0h] BYREF

  memset(s, 0, 0x1EuLL);
  printf("Please Input Key: ");
  __isoc99_scanf("%s", v5);
  encode(v5, (__int64)s);	//关键函数
  if ( strlen(v5) == key )
  {
    if ( !strcmp(s, enflag) )
      puts("You are Right");
    else
      puts("flag{This_1s_f4cker_flag}");
  }
  return 0;
}

所以关键是要知道 encode 函数怎么加密输入的,之后用 encode 解密enflag

int __fastcall encode(const char *a1, __int64 a2)
{
  char v3[104]; // [rsp+10h] [rbp-70h]
  int v4; // [rsp+78h] [rbp-8h]
  int i; // [rsp+7Ch] [rbp-4h]

  i = 0;
  v4 = 0;
  if ( strlen(a1) != key )				//12h,18位
    return puts("Your Length is Wrong");
  for ( i = 0; i < key; i += 3 )
  {
    v3[i + 64] = key ^ (a1[i] + 6);
    v3[i + 33] = (a1[i + 1] - 6) ^ key;
    v3[i + 2] = a1[i + 2] ^ 6 ^ key;		//加密算法
      
    *(_BYTE *)(a2 + i) = v3[i + 64];
    *(_BYTE *)(a2 + i + 1LL) = v3[i + 33];
    *(_BYTE *)(a2 + i + 2LL) = v3[i + 2];	//指针赋值
  }
  return a2;
}

python 脚本,加密脚本逆着小写,flag 就出来了。

#!/usr/bin/python
#"izwhroz\"\"w\"v.K\".Ni"
enflag=[105, 122, 119, 104, 114, 111, 122, 34, 34, 119, 34, 118, 46, 75, 34, 46, 78, 105, 0]
flag=''
for i in range(0,18,3):
    flag+=chr((18^enflag[i])-6)
    flag+=chr((18^enflag[i+1])+6)
    flag+=chr(18^enflag[i+2]^6)    
print(flag)

参考:

攻防世界-Reverse-666

CTF-Python常用函数语段详解

ASCII 在线转换器