quasar
bamuwe@bamuwe:~$ file quasar
quasar: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=00a219f57c37379e9a7d16a82edc8463bf5c4b8e, for GNU/Linux 4.4.0, stripped
64位程式
__int64 __fastcall main(int a1, char **a2, char **a3)
{
char s1[80]; // [rsp+10h] [rbp-A8h] BYREF
char s2[72]; // [rsp+60h] [rbp-58h] BYREF
unsigned __int64 v6; // [rsp+A8h] [rbp-10h]
v6 = __readfsqword(0x28u);
if ( a1 == 2 ) //判斷命令列輸入引數個數是否等於2
{
sub_1219(s1); //生成s1
sub_1414(s1, s1); //對s1進行加密
sub_1414(a2[1], s2); //對s2(~輸入)進行相同的加密
if ( !strcmp(s1, s2) ) //檢查點
system("/scripts/print.sh");
else
printf(&byte_2038);
}
else
{
puts("Uso: ./Quasar <password>");
}
return 0LL;
}
main
函式虛擬碼
s1
沒有現成的資料,我們需要得到程式執行過程中生成的s1
,簡單分析發現s1
在sub_1219(s1);
函式中生成
__int64 __fastcall sub_1219(__int64 a1)
{
double v1; // xmm0_8
double v2; // xmm0_8
int v3; // eax
__int64 result; // rax
double v5; // [rsp+8h] [rbp-30h]
double v6; // [rsp+8h] [rbp-30h]
double v7; // [rsp+8h] [rbp-30h]
int i; // [rsp+20h] [rbp-18h]
int j; // [rsp+24h] [rbp-14h]
double v10; // [rsp+28h] [rbp-10h]
for ( i = 0; i <= 9; ++i )
{
v10 = 0.0;
for ( j = 0; j <= 4; ++j )
{
v1 = sin(3.141592653589793 * i / 3.0 + j);
v5 = pow(v1, 2.0);
v6 = log((i + j + 3)) * v5;
v2 = sqrt((i + j + 1));
v7 = exp(v2) + v6;
v3 = i + j + 1;
if ( (i + j) < 0xFFFFFFFE && i + j != 0 )
v3 = 0;
v10 = tgamma((i + j + 1)) * v3 + v7 + v10;
}
*(i + a1) = (100.0 * v10) % 10 + 48;
}
result = a1 + 10;
*(a1 + 10) = 0;
return result;
}
我嘞個逗,這麼多數學函式~
一個雙重迴圈,進行一系列複雜的數學計算後得出a1
但是我們不關心他是怎麼算的,只要得到最後出來的結果就可以了,第一層迴圈迴圈$10$次,每次會得到一個result
值,拼接起來就是我們要的答案,因為後續會刪除*(a1 + 10) = 0;
,所以要一步步去看
操作:
-
先在第八行打個斷點,用來繞過輸入引數的檢測
-
ctrl+n
設定一個錨點,使程式轉跳到我們要的地方
-
在函式中設定一個合適的斷點,方便讀取資料
我們知道資料在result
中,要怎麼去讀取呢?
檢視相應的彙編程式碼可以知道,資料都存在rax
當中也就是說,我們只要讀取到rax
相應棧上的值就可以了
好巧,右上角就有一個可以看的視窗
得到答案了$9740252204$
?為什麼不分析接下來兩個函式呢?因為剩下兩個函式是對輸入和校驗值進行相同的加密操作,只要得到的校驗值對了,後面都是一樣的
by the way,操作有很多種方式
such as :
第一個命令列引數透過修改暫存器可以跳過
最後的值也可以在上圖右上角棧空間裡讀出,但是要注意大小端的問題
不看彙編的話虛擬碼中除錯每次賦值完看一次rax
也可以
總結:虛 張 聲 勢