因此,我正在研究“查找密碼”型別的二進制反匯編問題,但無法完全弄清楚。
組裝如下:
功能檢查pw
**************************************************************
* *
* FUNCTION *
**************************************************************
undefined8 __stdcall checkpw(void)
undefined8 RAX:8 <RETURN>
checkpw XREF[2]: Entry Point(*), main:001012a1(c)
00101179 48 89 c8 MOV RAX,RCX
0010117c 48 31 c1 XOR RCX,RAX
0010117f 8a 08 MOV CL,byte ptr [RAX]
00101181 80 f1 52 XOR CL,0x52
00101184 80 f9 11 CMP CL,0x11
00101187 75 5e JNZ LAB_001011e7
00101189 8a 48 07 MOV CL,byte ptr [RAX 0x7]
0010118c 80 e9 16 SUB CL,0x16
0010118f 80 f9 0d CMP CL,0xd
00101192 75 53 JNZ LAB_001011e7
00101194 8a 48 01 MOV CL,byte ptr [RAX 0x1]
00101197 48 31 d2 XOR RDX,RDX
0010119a fe c2 INC DL
0010119c 48 d1 e2 SHL RDX,1
0010119f 40 8a 3c 10 MOV DIL,byte ptr [RAX RDX*0x1]
001011a3 40 30 cf XOR DIL,CL
001011a6 40 80 ff 40 CMP DIL,0x40
001011aa 75 3b JNZ LAB_001011e7
001011ac 80 c1 63 ADD CL,0x63
001011af 80 f9 d6 CMP CL,0xd6
001011b2 75 33 JNZ LAB_001011e7
001011b4 8a 4c 10 01 MOV CL,byte ptr [RAX RDX*0x1 0x1]
001011b8 80 f9 23 CMP CL,0x23
001011bb 7e 2a JLE LAB_001011e7
001011bd 80 c1 5b ADD CL,0x5b
001011c0 70 25 JO LAB_001011e7
001011c2 48 8d 0c 50 LEA RCX,[RAX RDX*0x2]
001011c6 8a 09 MOV CL,byte ptr [RCX]
001011c8 80 f1 f3 XOR CL,0xf3
001011cb 80 f9 c7 CMP CL,0xc7
001011ce 75 17 JNZ LAB_001011e7
001011d0 8a 48 05 MOV CL,byte ptr [RAX 0x5]
001011d3 8a 68 06 MOV CH,byte ptr [RAX 0x6]
001011d6 66 81 f1 XOR CX,0x4c47
47 4c
001011db 66 81 f9 CMP CX,0x1234
34 12
001011e0 75 05 JNZ LAB_001011e7
001011e2 48 31 c0 XOR RAX,RAX
001011e5 eb 05 JMP LAB_001011ec
LAB_001011e7 XREF[8]: 00101187(j), 00101192(j),
001011aa(j), 001011b2(j),
001011bb(j), 001011c0(j),
001011ce(j), 001011e0(j)
001011e7 b8 01 00 MOV EAX,0x1
00 00
LAB_001011ec XREF[1]: 001011e5(j)
001011ec c3 RET
根據 Ghidra 的說法,反編譯的函式是:
undefined8 checkpw(void)
{
undefined8 uVar1;
char *in_RCX;
if (((((*in_RCX != 'C') || (in_RCX[7] != '#')) || ((byte)(in_RCX[2] ^ in_RCX[1]) != 0x40)) ||
((in_RCX[1] != 0x73 || (in_RCX[3] < '$')))) ||
((SCARRY1(in_RCX[3],'[') || ((in_RCX[4] != '4' || (*(short *)(in_RCX 5) != 0x5e73)))))) {
uVar1 = 1;
}
else {
uVar1 = 0;
}
return uVar1;
}
它將主函式反編譯為:
void main(int param_1,long param_2)
{
long lVar1;
size_t sVar2;
undefined8 uVar3;
lVar1 = ptrace(PTRACE_TRACEME,0,1,0);
if (lVar1 < 0) {
/* WARNING: Subroutine does not return */
exit(1);
}
if (param_1 != 2) {
/* WARNING: Subroutine does not return */
exit(2);
}
sVar2 = strlen(*(char **)(param_2 8));
if (sVar2 != 8) {
/* WARNING: Subroutine does not return */
exit(3);
}
uVar3 = checkpw();
if ((int)uVar3 != 0) {
puts("Invalid Password!");
/* WARNING: Subroutine does not return */
exit(4);
}
puts("Correct Password!");
/* WARNING: Subroutine does not return */
exit(0);
}
在這一點上,我可以告訴密碼必須是 8 個字符。
同樣基于 checkpw 反編譯,我相信以下是正確的(假設變數 passwd 是一個包含有效密碼的字符陣列):
passwd[0] = 'C'
passwd[1] = 's'
passwd[2] = '3'
passwd[3] = '$'
passwd[4] = '4'
passwd[7] = '#'
盡管我對其中的一些人并不完全有信心,但我確實對位置 5 和 6的人有麻煩。
反編譯的函式似乎沒有參考第七個字符,所以我假設它可以是任何東西,但不確定這意味著什么,因為它與這個問題有關:
(*(short *)(in_RCX 5) != 0x5e73)
uj5u.com熱心網友回復:
這:
(*(short *)(in_RCX 5) != 0x5e73)
一次比較兩個字符。該陳述句正在計算in_RCX 5然后將其轉換為short *即指向 16 位有符號整數的指標(函式體中使用的暫存器實際上是 RAX,盡管反編譯代碼中此變數的名稱)。然后它取消參考所述指標以一次獲取兩個位元組,并將它們與0x5e73. 當然,這只是反編譯的代碼,所以并不代表程式實際上是在做一個 16 位的 MOV(確實是在做兩個 8 位的 MOV),只是反編譯器認為的 C 版本而已繼續。
您可以在反匯編中更清楚地看到這一點:
001011d0 8a 48 05 MOV CL,byte ptr [RAX 0x5]
001011d3 8a 68 06 MOV CH,byte ptr [RAX 0x6]
001011d6 66 81 f1 XOR CX,0x4c47
47 4c
001011db 66 81 f9 CMP CX,0x1234
34 12
001011e0 75 05 JNZ LAB_001011e7
0x4c47反匯編中的檢查是使用 XOR CMP JNZ 完成的,所以 Ghidra 已經0x1234為您進行了異或運算,即0x5e73. 這意味著為了使檢查通過,passwd[5]必須是0x73( 's') 并且passwd[6]必須是0x5e( '^')。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/420272.html
標籤:
