CTFSHOW-Reverse-刷題記錄


re2

打開初步分析為32位程序,無殼,拖入IDA32分析

re2_main

找到關鍵行47-50,分析得出各函數內部的基本作用如圖所示

首先進入分析輸入后的處理re2_401A70

可以很明顯看出,是對輸入的字符串進行處理后再操作,因此根據這個思路寫出腳本,得到這里的密鑰

#!/usr/bin/python
#coding=utf-8

user = "DH~mqqvqxB^||zll@Jq~jkwpmvez{"

flag = ''
for x in range(0, 29):
    for y in range(256):
        if(ord(user[x])==y^0x1f):
            flag+=chr(y)

print(flag) #[Warnning]Access_Unauthorized

接着分析加密函數,對加密函數內各函數分析后可得出大致為RC4,因此只要根據給出的加密內容進行逆向解密即可

re2_4014E0

但是這里加密后的是什么內容是什么不清楚,我盲猜是給出的壓縮文件里面的文本,但是這里沒有科學依據,后來看到一篇大師傅的WP,他的分析是程序在最初會對enflag.txt的內容進行fopen() w操作,這樣會清楚里面的文本,照此來看里面的東西其實沒有被用過,因此可以推斷他就是要加密的原始文本,因此在同目錄下創建flag.txt,放入文本,解密成功。

re2_flag

r2

打開后得到如下偽代碼

int __cdecl main(int argc, const char **argv, const char **envp)
{
  size_t v3; // rax
  int v5; // [rsp+Ch] [rbp-134h] BYREF
  unsigned int i; // [rsp+10h] [rbp-130h]
  int v7; // [rsp+14h] [rbp-12Ch]
  int v8; // [rsp+18h] [rbp-128h]
  int v9; // [rsp+1Ch] [rbp-124h]
  int v10; // [rsp+20h] [rbp-120h]
  int v11; // [rsp+24h] [rbp-11Ch]
  int v12; // [rsp+28h] [rbp-118h]
  int v13; // [rsp+2Ch] [rbp-114h]
  int v14; // [rsp+30h] [rbp-110h]
  int v15; // [rsp+34h] [rbp-10Ch]
  unsigned __int64 v16; // [rsp+38h] [rbp-108h]
  int v17[8]; // [rsp+40h] [rbp-100h]
  char s[5]; // [rsp+60h] [rbp-E0h] BYREF
  char v19[107]; // [rsp+65h] [rbp-DBh] BYREF
  char dest[104]; // [rsp+D0h] [rbp-70h] BYREF
  unsigned __int64 v21; // [rsp+138h] [rbp-8h]

  v21 = __readfsqword(0x28u);
  v7 = 80;
  v8 = 64227;
  v9 = 226312059;
  v10 = -1540056586;
  v11 = 5;
  v12 = 16;
  v13 = 3833;
  v5 = 0;
  puts("plz input the key:");
  __isoc99_scanf("%s", s);	// 輸入key
  v3 = strlen(s);	// 計算輸入長度
  strncpy(dest, v19, v3 - 6);	// 將s的6~strlen(s)-1位復制到dest,輸入s的長度不小於6
  dest[strlen(s) - 6] = 0;	// 最后1位置0
  __isoc99_sscanf(dest, "%x", &v5);	 // 讀取dest中16進制數到v5
  v17[0] = v7;
  v17[1] = v8;
  v17[2] = v9;
  v17[3] = v10;
  v17[4] = (v11 << 12) + v12;
  v17[5] = v13;
  v17[6] = v5;
  v16 = 0LL;
  for ( i = 0; i <= 6; ++i )
  {
    for ( v16 += (unsigned int)v17[i]; v16 > 0xFFFF; v16 = v15 + (unsigned int)(unsigned __int16)v16 )// unsigned __int16只保留后4位
    {
      v14 = (unsigned __int16)v16;	// 沒用到v14,這行可以忽略
      v15 = v16 >> 16;
    }
  }
  if ( v16 == 0xFFFF )
    puts("OK");
  else
    puts("Error");
  return 0;
}

從47行可見v16分別加上了v17的前6位,因此前6位是保持不變的,根據題意,v17[6]就是所要求的flag,所以這里可以寫出如下程序

#include<stdio.h>
int main() {
	int v15 = 0;
	unsigned __int64 v16 = 0LL;
	int v17[7] = {80, 64227, 226312059, -1540056586, 20496, 3833, 888};

	for (int i = 0 ; i <= 6; ++i ) {
		for ( v16 += (unsigned int)v17[i]; v16 > 0xFFFF; v16 = v15 + (unsigned int)(unsigned __int16)v16 )
			v15 = v16 >> 16;
	}

	if ( v16 == 0xFFFF )
		puts("OK");
	else
		puts("Error");

	return 0;
}

調試到即將與v17[6]相加的地方

r2_debug

v16先加上v17[6],然后判斷是否大於0xffff,小於等於0xffff即退出循環,由提示最小解,4位值,直接相減就可得出最終結果,最終得到flag即為flag{1a9f}

數學不及格_re3

用IDA打開,可以看到是一個類似於數學方程問題

re3_main

這里看到v9的值是v4經過函數f處理之后的值,再看一下函數f

re3_f

可以看出f函數是一個斐波那契的處理過程

這里的處理應當為四個判斷等式聯立求解,划掉v10-v12,得v4+3*v9;又因為v9為v4下標范圍內的斐波拉契數列值,因此通過0<v4<200,有爆破可能性,直接遍歷爆破v4與v9。(v4=58,v9=591286729879),后面依次求解v10-v12,並把它們轉化為字符串,由此可寫出python腳本

def f(n):
    li=[]
    v9=0
    li.append(1)
    li.append(1)
    for i in range(2, n):
        li.append(li[i-1] + li[i-2])
        v9=li[i]
    return v9

for i in range(1, 199):
    v4 = i
    v9=f(v4)
    if(v4+3*v9==151381742876+117138004530+155894355749+1349446086540):
        print(v4, v9)
        break

v10 = hex(151381742876-v9)
v11 = hex(117138004530-v9)
v12 = hex(155894355749-v9)

s='666c61677b6e65776265655f686572657d'
flag=''
for i in range(0, len(s), 2):
    flag+=chr(int(s[i:i+2], 16))
print(flag)

可得出結果如下

re3_result

得到flag問題得解


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM