Reverse Engineering
Last updated
Last updated
Challenge | Link |
---|---|
-
Given PE file, open it using IDA.
Main function not detected, but it still easy to find since start function is common start function.
So sub_401530 is main function, set breakpoint on that function. Set breakpoint at 0x0040165F and step instruction to enter the function.
call near ptr unk_1E7210
edx+4 == 0x1e000d
So function unk_1E7210 do self modification by doing some operation such as substract, xor, rol, and add.
From image above we can see that the code is different after mov edi,edi. Lets disassemble again code after mov edi,edi by pressing c on address 0x1e000d.
Continue the process by stepping instruction we will get into looping at 0x1e0028.
Loop instruction will do looping until ecx is 0. So we can said that it will overwrite value until 0x1e0029 (edx + 0x17). If we set breakpoint on those address the debugger will error, so the idea is set hardware breakpoint on 0x1e002a and continue the process.
Now the values start from 0x1e002a are different again.
Scrolling down i saw valid PE file, dump it using IDC.
auto fname = "C:\\Users\\Intel NUC\\ctf\\ascwg\\amber\\dump_pe.exe";
auto address = 0x01E0031;
auto size = 0x71df;
auto file= fopen(fname, "wb");
savefile(file, 0, address, size);
fclose(file);
dump_pe.exe actually a valid PE and consist of some functions but since it written dynamically there are some imported function not detected. So i choose to continue current debugginer. Disassemble code again and do step instruction again.
Continue the process until call near ptr unk_1e7031.
sub_1E717C: resolve function based on hash value
After manually check what function called, here is the summary
debug078:001E7059 call sub_1E717C ; virtual alloc, 2C39DFECh
debug078:001E70D9 call sub_1E7143 ; LoadLibrary, 0E2E6A091h
debug078:001E70E3 call sub_1E70F1 ; GetProcAddress, 0A18B0B38h
Next, set breakpoint on last instruction on sub_1F7033 (0x01F7177).
Step into sub_1f71fd again and set breakpoint on 0x01F720E.
Step into on call edi and do step over so we will not get into call unk_7FE71CB2.
Now we are on start function of new executable sub_7FE71737.
Again, we can find which one main function by manually validating it.
Set breakpoint on new main function then continue the program.
Rename all function. Original function name can be found by double click the address.
int sub_7FE7134E()
{
char v0; // bl
int v1; // ebx
char v2; // al
int CurrentProcess; // eax
int LibraryW; // eax
int (__stdcall *v5)(int, char *); // edi
int (__stdcall *ProcAddress)(int, _DWORD, int *, int, int *); // esi
int v7; // eax
char v8; // al
void (__stdcall *v9)(wchar_t *, _DWORD); // esi
int v10; // eax
void (__stdcall *v11)(int); // esi
int CurrentThread; // eax
char v13; // al
unsigned int v14; // kr00_4
unsigned __int64 v15; // rax
unsigned __int64 v16; // rax
void (__thiscall *func_kernel32_QueryPerformanceCounter)(int, __int64 *); // esi
int v18; // ecx
bool v19; // sf
bool v20; // cc
int (__thiscall *func_kernel32_GetTickCount)(int); // esi
char v22; // al
int TickCount; // edi
int v24; // ecx
_BYTE *ciphertext; // [esp+30h] [ebp-80h]
int v27[6]; // [esp+34h] [ebp-7Ch] BYREF
__int64 v28; // [esp+4Ch] [ebp-64h] BYREF
__int64 v29; // [esp+54h] [ebp-5Ch] BYREF
int v30; // [esp+5Ch] [ebp-54h] BYREF
int v31; // [esp+60h] [ebp-50h] BYREF
int length[4]; // [esp+64h] [ebp-4Ch] BYREF
char v33; // [esp+74h] [ebp-3Ch]
char v34; // [esp+75h] [ebp-3Bh]
int v35; // [esp+76h] [ebp-3Ah]
char v36; // [esp+7Ah] [ebp-36h]
int v37; // [esp+7Bh] [ebp-35h]
int v38; // [esp+7Fh] [ebp-31h]
int v39; // [esp+83h] [ebp-2Dh]
int v40; // [esp+87h] [ebp-29h]
int v41; // [esp+8Bh] [ebp-25h]
int v42; // [esp+8Fh] [ebp-21h]
__int16 v43; // [esp+93h] [ebp-1Dh]
int key; // [esp+98h] [ebp-18h] BYREF
int key2; // [esp+9Ch] [ebp-14h]
int key3; // [esp+A0h] [ebp-10h]
int key4; // [esp+A4h] [ebp-Ch]
__int16 key5; // [esp+A8h] [ebp-8h]
ciphertext = (_BYTE *)ucrtbase_malloc_(192);
length[0] = 0x966FB0FA;
length[1] = 0xEA1A5D26;
key2 = 0;
length[2] = 0xB957D429;
length[3] = 0xBC71485;
v33 = 0x64;
key3 = 0;
v35 = 0xD90954E9;
v37 = 0x3A6DBCD1;
v38 = 0xA9C0CC4D;
key4 = 0;
v39 = 0x309EAB99;
v40 = 0x443FF4C2;
v41 = 0xE914B72D;
key5 = 0;
v0 = 0x63;
v34 = 0x1E;
v36 = 0x63;
v42 = 0x37317856;
v43 = 0xEA;
v31 = 0;
key = (unsigned __int8)(102 - (kernel32_IsDebuggerPresent_() != 0));
if ( (unsigned __int8)*(_DWORD *)&NtCurrentPeb()->BeingDebugged )
v0 = 50;
BYTE1(key) = v0;
v1 = 0;
v31 = 0;
v2 = 102;
if ( (NtCurrentPeb()->NtGlobalFlag & 0x70) != 0 )
v2 = 97;
v31 = 0;
BYTE2(key) = v2;
CurrentProcess = kernel32_GetCurrentProcess_();
kernel32_CheckRemoteDebuggerPresent_(CurrentProcess, &v31);
v30 = 0;
HIBYTE(key) = (v31 != 0) + 48;
memset(v27, 0, sizeof(v27));
LibraryW = kernel32_LoadLibraryW_(aNtdllDll);
v5 = (int (__stdcall *)(int, char *))kernel32_GetProcAddress_;
if ( LibraryW != -1
&& LibraryW
&& (ProcAddress = (int (__stdcall *)(int, _DWORD, int *, int, int *))kernel32_GetProcAddress_(
LibraryW,
aNtqueryinforma)) != 0 )
{
v7 = kernel32_GetCurrentProcess_();
if ( ProcAddress(v7, 0, v27, 24, &v30) >= 0 && v27[1] )
v8 = (*(_BYTE *)(v27[1] + 2) == 0) + 54;
else
v8 = (char)ciphertext;
}
else
{
v8 = 0;
}
v9 = (void (__stdcall *)(wchar_t *, _DWORD))user32_FindWindowW_;
LOBYTE(key2) = v8;
user32_FindWindowW_(aX86, 0);
v9(aId, 0);
BYTE1(key2) = 49;
v10 = kernel32_LoadLibraryW_(aNtdllDll);
if ( v10 != -1 && v10 && (v11 = (void (__stdcall *)(int))v5(v10, aNtsetinformati)) != 0 )
{
CurrentThread = kernel32_GetCurrentThread_(17, 0, 0);
v11(CurrentThread);
v13 = 50;
}
else
{
v13 = 0;
}
BYTE2(key2) = v13;
HIBYTE(key2) = anti_debug_1();
v14 = __readeflags();
LOBYTE(key3) = ((v14 & 0x100) == 0) + 51;
v15 = __rdtsc();
HIDWORD(v28) = HIDWORD(v15);
v30 = v15;
v16 = __rdtsc();
HIDWORD(v29) = HIDWORD(v16);
v31 = v16;
func_kernel32_QueryPerformanceCounter = (void (__thiscall *)(int, __int64 *))kernel32_QueryPerformanceCounter_;
BYTE1(key3) = ((int)v16 - v30 <= (int)&unk_10000) + 56;
kernel32_QueryPerformanceCounter_(&v28);
func_kernel32_QueryPerformanceCounter(-16 * v18, &v29);
v19 = (((unsigned __int64)(v29 - v28) >> 32) & 0x80000000) != 0i64;
v20 = v29 < v28 || (unsigned __int64)(v29 - v28) >> 32 == 0;
HIDWORD(v29) = (unsigned __int64)(v29 - v28) >> 32;
if ( !v19 && (!v20 || (unsigned int)(v29 - v28) > 0x1E) )
v1 = 1;
func_kernel32_GetTickCount = (int (__thiscall *)(int))kernel32_GetTickCount_;
v22 = 98;
if ( !v1 )
v22 = 52;
BYTE2(key3) = v22;
TickCount = kernel32_GetTickCount_(v14);
HIBYTE(key3) = (unsigned int)(func_kernel32_GetTickCount(-16 * v24) - TickCount) > 0x1E ? 99 : 101;
LOBYTE(key4) = func_closehandle();
BYTE1(key4) = return_const_1();
BYTE2(key4) = return_const_2();
HIBYTE(key4) = return_const_3();
LOBYTE(key5) = return_const_4();
return RC4((const char *)&key, (int)length, ciphertext);
}
debug078:7FE7109A sub_7FE7109A proc near ; CODE XREF: sub_7FE7134E+29E↓p
debug078:7FE7109A ; __unwind { // sub_7FE71F70
debug078:7FE7109A push 8
debug078:7FE7109C push offset unk_7FE73598
debug078:7FE710A1 call sub_7FE71F70
debug078:7FE710A6 xor esi, esi
debug078:7FE710A8 ; __try { // __except at 7FE710BC
debug078:7FE710A8 mov [ebp-4], esi
debug078:7FE710AB push 0BEEFh ; hObject
debug078:7FE710B0 call CloseHandle_
debug078:7FE710B6 jmp short loc_7FE710C2
debug078:7FE710B8 ; ---------------------------------------------------------------------------
debug078:7FE710B8 ; __except filter // owned by 7FE710A8
debug078:7FE710B8 xor eax, eax
debug078:7FE710BA inc eax
debug078:7FE710BB retn
debug078:7FE710BC ; ---------------------------------------------------------------------------
debug078:7FE710BC ; __except(7FE710B8) // owned by 7FE710A8
debug078:7FE710BC mov esp, [ebp-18h]
debug078:7FE710BF xor esi, esi
debug078:7FE710C1 inc esi
debug078:7FE710C1 ; } // starts at 7FE710A8
debug078:7FE710C2
debug078:7FE710C2 loc_7FE710C2: ; CODE XREF: sub_7FE7109A+1C↑j
debug078:7FE710C2 mov dword ptr [ebp-4], 0FFFFFFFEh
debug078:7FE710C9 xor eax, eax
debug078:7FE710CB test esi, esi
debug078:7FE710CD setnz al
debug078:7FE710D0 add eax, 64h ; 'd'
debug078:7FE710D3 mov ecx, [ebp-10h]
debug078:7FE710D6 mov large fs:0, ecx
debug078:7FE710DD pop ecx
debug078:7FE710DE pop edi
debug078:7FE710DF pop esi
debug078:7FE710E0 pop ebx
debug078:7FE710E1 leave
debug078:7FE710E2 retn
debug078:7FE710E3 ; __unwind { // sub_7FE71F70
debug078:7FE710E3 push 8
debug078:7FE710E5 push offset unk_7FE735B8
debug078:7FE710EA call sub_7FE71F70
debug078:7FE710EF xor eax, eax
debug078:7FE710F1 inc eax
debug078:7FE710F2 ; __try { // __except at 7FE71103
debug078:7FE710F2 and dword ptr [ebp-4], 0
debug078:7FE710F6 pushf
debug078:7FE710F7 or [esp+0Ch+var_B], 1
debug078:7FE710FC popf
debug078:7FE710FD jmp short loc_7FE71108
debug078:7FE710FF ; ---------------------------------------------------------------------------
debug078:7FE710FF ; __except filter // owned by 7FE710F2
debug078:7FE710FF xor eax, eax
debug078:7FE71101 inc eax
debug078:7FE71102 retn
debug078:7FE71103 ; ---------------------------------------------------------------------------
debug078:7FE71103 ; __except(7FE710FF) // owned by 7FE710F2
debug078:7FE71103 mov esp, [ebp-18h]
debug078:7FE71106 xor eax, eax
debug078:7FE71106 ; } // starts at 7FE710F2
debug078:7FE71108
debug078:7FE71108 loc_7FE71108: ; CODE XREF: sub_7FE710E3+1A↑j
debug078:7FE71108 mov dword ptr [ebp-4], 0FFFFFFFEh
debug078:7FE7110F neg eax
debug078:7FE71111 sbb eax, eax
debug078:7FE71113 add eax, 33h ; '3'
debug078:7FE71116 mov ecx, [ebp-10h]
debug078:7FE71119 mov large fs:0, ecx
debug078:7FE71120 pop ecx
debug078:7FE71121 pop edi
debug078:7FE71122 pop esi
debug078:7FE71123 pop ebx
debug078:7FE71124 leave
debug078:7FE71125 retn
debug078:7FE71126 sub_7FE71126 proc near ; CODE XREF: sub_7FE7134E+2AE↓p
debug078:7FE71126 ; __unwind { // sub_7FE71F70
debug078:7FE71126 push 8
debug078:7FE71128 push offset unk_7FE735D8
debug078:7FE7112D call sub_7FE71F70
debug078:7FE71132 xor ecx, ecx
debug078:7FE71134 inc ecx
debug078:7FE71135 ; __try { // __except at 7FE71140
debug078:7FE71135 and dword ptr [ebp-4], 0
debug078:7FE71139 int 3 ; Trap to Debugger
debug078:7FE7113A jmp short loc_7FE71145
debug078:7FE7113C ; ---------------------------------------------------------------------------
debug078:7FE7113C ; __except filter // owned by 7FE71135
debug078:7FE7113C xor eax, eax
debug078:7FE7113E inc eax
debug078:7FE7113F retn
debug078:7FE71140 ; ---------------------------------------------------------------------------
debug078:7FE71140 ; __except(7FE7113C) // owned by 7FE71135
debug078:7FE71140 mov esp, [ebp-18h]
debug078:7FE71143 xor ecx, ecx
debug078:7FE71143 ; } // starts at 7FE71135
debug078:7FE71145
debug078:7FE71145 loc_7FE71145: ; CODE XREF: sub_7FE71126+14↑j
debug078:7FE71145 mov dword ptr [ebp-4], 0FFFFFFFEh
debug078:7FE7114C xor eax, eax
debug078:7FE7114E test ecx, ecx
debug078:7FE71150 setnz al
debug078:7FE71153 add eax, 61h ; 'a'
debug078:7FE71156 mov ecx, [ebp-10h]
debug078:7FE71159 mov large fs:0, ecx
debug078:7FE71160 pop ecx
debug078:7FE71161 pop edi
debug078:7FE71162 pop esi
debug078:7FE71163 pop ebx
debug078:7FE71164 leave
debug078:7FE71165 retn
debug078:7FE711AC sub_7FE711AC proc near ; CODE XREF: sub_7FE7134E+2B6↓p
debug078:7FE711AC ; __unwind { // sub_7FE71F70
debug078:7FE711AC push 8
debug078:7FE711AE push offset unk_7FE73618
debug078:7FE711B3 call sub_7FE71F70
debug078:7FE711B8 xor ecx, ecx
debug078:7FE711BA inc ecx
debug078:7FE711BB ; __try { // __except at 7FE711C8
debug078:7FE711BB and dword ptr [ebp-4], 0
debug078:7FE711BF int 2Dh ; Windows NT - debugging services: eax = type
debug078:7FE711C1 nop
debug078:7FE711C2 jmp short loc_7FE711CD
debug078:7FE711C4 ; ---------------------------------------------------------------------------
debug078:7FE711C4 ; __except filter // owned by 7FE711BB
debug078:7FE711C4 xor eax, eax
debug078:7FE711C6 inc eax
debug078:7FE711C7 retn
debug078:7FE711C8 ; ---------------------------------------------------------------------------
debug078:7FE711C8 ; __except(7FE711C4) // owned by 7FE711BB
debug078:7FE711C8 mov esp, [ebp-18h]
debug078:7FE711CB xor ecx, ecx
debug078:7FE711CB ; } // starts at 7FE711BB
debug078:7FE711CD
debug078:7FE711CD loc_7FE711CD: ; CODE XREF: sub_7FE711AC+16↑j
debug078:7FE711CD mov dword ptr [ebp-4], 0FFFFFFFEh
debug078:7FE711D4 push 33h ; '3'
debug078:7FE711D6 pop eax
debug078:7FE711D7 push 31h ; '1'
debug078:7FE711D9 pop edx
debug078:7FE711DA test ecx, ecx
debug078:7FE711DC cmovnz eax, edx
debug078:7FE711DF mov ecx, [ebp-10h]
debug078:7FE711E2 mov large fs:0, ecx
debug078:7FE711E9 pop ecx
debug078:7FE711EA pop edi
debug078:7FE711EB pop esi
debug078:7FE711EC pop ebx
debug078:7FE711ED leave
debug078:7FE711EE retn
debug078:7FE71126 sub_7FE71126 proc near ; CODE XREF: sub_7FE7134E+2AE↓p
debug078:7FE71126 ; __unwind { // sub_7FE71F70
debug078:7FE71126 push 8
debug078:7FE71128 push offset unk_7FE735D8
debug078:7FE7112D call sub_7FE71F70
debug078:7FE71132 xor ecx, ecx
debug078:7FE71134 inc ecx
debug078:7FE71135 ; __try { // __except at 7FE71140
debug078:7FE71135 and dword ptr [ebp-4], 0
debug078:7FE71139 int 3 ; Trap to Debugger
debug078:7FE7113A jmp short loc_7FE71145
debug078:7FE7113C ; ---------------------------------------------------------------------------
debug078:7FE7113C ; __except filter // owned by 7FE71135
debug078:7FE7113C xor eax, eax
debug078:7FE7113E inc eax
debug078:7FE7113F retn
debug078:7FE71140 ; ---------------------------------------------------------------------------
debug078:7FE71140 ; __except(7FE7113C) // owned by 7FE71135
debug078:7FE71140 mov esp, [ebp-18h]
debug078:7FE71143 xor ecx, ecx
debug078:7FE71143 ; } // starts at 7FE71135
debug078:7FE71145
debug078:7FE71145 loc_7FE71145: ; CODE XREF: sub_7FE71126+14↑j
debug078:7FE71145 mov dword ptr [ebp-4], 0FFFFFFFEh
debug078:7FE7114C xor eax, eax
debug078:7FE7114E test ecx, ecx
debug078:7FE71150 setnz al
debug078:7FE71153 add eax, 61h ; 'a'
debug078:7FE71156 mov ecx, [ebp-10h]
debug078:7FE71159 mov large fs:0, ecx
debug078:7FE71160 pop ecx
debug078:7FE71161 pop edi
debug078:7FE71162 pop esi
debug078:7FE71163 pop ebx
debug078:7FE71164 leave
debug078:7FE71165 retn
int __fastcall RC4(const char *key, int length, _BYTE *ciphertext)
{
signed int v3; // esi
int v4; // edi
int i; // eax
int v6; // ecx
unsigned __int8 v7; // bl
int v10; // [esp+18h] [ebp-108h]
char keystream[256]; // [esp+1Ch] [ebp-104h] BYREF
v3 = strlen(key);
v4 = 0;
for ( i = 0; i < 256; ++i )
keystream[i] = i;
v6 = 0;
v10 = 0;
do
{
v7 = keystream[v6];
v4 = (v7 + key[v6 % v3] + v4) % 256;
keystream[v10] = keystream[v4];
v6 = v10 + 1;
keystream[v4] = v7;
v10 = v6;
}
while ( v6 < 256 );
RC4_enc((int)keystream, length, ciphertext);
return 0;
}
Function func_closehandle, return_const_1 - return_const_4 basically do try catch with anti debug mechanism. The possibility of the value returned only two, if there is no exception will be A and if there is exception will be B. So we can conclude that it is possible to brute it. At the end we need to find the correct key and ciphertext to get the flag through RC4 decryption. Because there are so many anti debug check, the easy way to solve it just by bruteforcing all possibility (key, key2, key3, key4, key5). key-key5 actually one key (contiguous memory location/no null byte between variable location), it divided to 5 variables because decompiler mechanism.
from Crypto.Cipher import ARC4
from itertools import product
list_key = [[] for i in range(17)]
# key
list_key[0] = [0x66, 0x65]
list_key[1] = [0x63, 0x32]
list_key[2] = [0x66, 0x61]
list_key[3] = [0x30, 0x31]
# key2
list_key[4] = [0x36, 0x37]
list_key[5] = [0x31]
list_key[6] = [0x32, 0x0]
list_key[7] = [0x62, 0x61]
# key3
list_key[8] = [0x33, 0x34]
list_key[9] = [0x38, 0x39]
list_key[10] = [0x62, 0x34]
list_key[11] = [0x63, 0x65]
# key4
list_key[12] = [0x64, 0x65]
list_key[13] = [0x33, 0x34]
list_key[14] = [0x61, 0x62]
list_key[15] = [0x31, 0x33]
# key5
list_key[16] = [0x61, 0x62]
ct = "FA B0 6F 96 26 5D 1A EA 29 D4 57 B9 85 14 C7 0B 64 1E E9 54 09 D9 63 D1 BC 6D 3A 4D CC C0 A9 99 AB 9E 30 C2 F4 3F 44 2D B7 14 E9 56 78 31 37 EA"
ct = [int(i, 16) for i in ct.split(" ")]
ct = bytes(ct)
for i in product(*list_key):
tmp_key = bytes(i)
cipher = ARC4.new(bytes(tmp_key))
pt = cipher.decrypt(ct)
if b"ASCWG" in pt:
print(tmp_key, pt)
Flag: ASCWG{What_A_ReverseEngineering_Beast_13337_-_-}
Given assembly code below
.LC0:
.string "Enter The Flag:"
.LC1:
.string "%s"
.LC2:
.string "Wrong Flag"
.LC3:
.string "Correct Flag"
flag_check():
push rbp
mov rbp, rsp
sub rsp, 464
mov QWORD PTR [rbp-112], 0
mov QWORD PTR [rbp-104], 0
mov QWORD PTR [rbp-96], 0
mov QWORD PTR [rbp-88], 0
mov QWORD PTR [rbp-80], 0
mov QWORD PTR [rbp-72], 0
mov QWORD PTR [rbp-64], 0
mov QWORD PTR [rbp-56], 0
mov QWORD PTR [rbp-48], 0
mov QWORD PTR [rbp-40], 0
mov QWORD PTR [rbp-32], 0
mov QWORD PTR [rbp-24], 0
mov DWORD PTR [rbp-16], 0
mov edi, OFFSET FLAT:.LC0
call puts
lea rax, [rbp-112]
mov rsi, rax
mov edi, OFFSET FLAT:.LC1
mov eax, 0
call __isoc99_scanf
movabs rax, -871222578553387942
movabs rdx, -3456440840989770153
mov QWORD PTR [rbp-368], rax
mov QWORD PTR [rbp-360], rdx
movabs rax, -6917285895965957581
movabs rdx, 2096695603964784419
mov QWORD PTR [rbp-352], rax
mov QWORD PTR [rbp-344], rdx
movabs rax, 4501421280245125089
movabs rdx, -5989732096912246845
mov QWORD PTR [rbp-336], rax
mov QWORD PTR [rbp-328], rdx
movabs rax, -7641474145812966946
movabs rdx, 5943263215614115999
mov QWORD PTR [rbp-320], rax
mov QWORD PTR [rbp-312], rdx
movabs rax, 3346881274156629838
movabs rdx, -4046563652848771978
mov QWORD PTR [rbp-304], rax
mov QWORD PTR [rbp-296], rdx
movabs rax, 1600213061547397258
movabs rdx, -7907006450299616387
mov QWORD PTR [rbp-288], rax
mov QWORD PTR [rbp-280], rdx
movabs rax, 2641250925692849876
movabs rdx, 5764027888120773659
mov QWORD PTR [rbp-272], rax
mov QWORD PTR [rbp-264], rdx
movabs rax, -2708211178971868809
movabs rdx, -1437889653997315907
mov QWORD PTR [rbp-256], rax
mov QWORD PTR [rbp-248], rdx
movabs rax, -1790267167538066993
movabs rdx, 6751799815650390725
mov QWORD PTR [rbp-240], rax
mov QWORD PTR [rbp-232], rdx
movabs rax, -7155949167227380485
movabs rdx, -240513889820188763
mov QWORD PTR [rbp-224], rax
mov QWORD PTR [rbp-216], rdx
movabs rax, 8430573516374475283
movabs rdx, 7014569824855873983
mov QWORD PTR [rbp-208], rax
mov QWORD PTR [rbp-200], rdx
movabs rax, -1194317526320485479
movabs rdx, -2635243135622213470
mov QWORD PTR [rbp-192], rax
mov QWORD PTR [rbp-184], rdx
movabs rax, 3816607778456458796
movabs rdx, 7739645478794557909
mov QWORD PTR [rbp-176], rax
mov QWORD PTR [rbp-168], rdx
movabs rax, 2239858223738625365
movabs rdx, 6262919446888351940
mov QWORD PTR [rbp-160], rax
mov QWORD PTR [rbp-152], rdx
movabs rax, 5359968574739497219
movabs rdx, -5945185636638990574
mov QWORD PTR [rbp-144], rax
mov QWORD PTR [rbp-136], rdx
movabs rax, 4289602485438450409
movabs rdx, -4136753309120802266
mov QWORD PTR [rbp-128], rax
mov QWORD PTR [rbp-120], rdx
movabs rax, 3689636007142570038
movabs rdx, 7149575679097845041
mov QWORD PTR [rbp-400], rax
mov QWORD PTR [rbp-392], rdx
movabs rax, 3544442000607754086
movabs rdx, 58494055442021
mov QWORD PTR [rbp-390], rax
mov QWORD PTR [rbp-382], rdx
movabs rax, -6712584965997026559
movabs rdx, 5818345077617353901
mov QWORD PTR [rbp-464], rax
mov QWORD PTR [rbp-456], rdx
movabs rax, -1172694937141806812
movabs rdx, -4970398359911696349
mov QWORD PTR [rbp-448], rax
mov QWORD PTR [rbp-440], rdx
movabs rax, -7528756344694355204
movabs rdx, -880185776627970324
mov QWORD PTR [rbp-432], rax
mov QWORD PTR [rbp-424], rdx
mov WORD PTR [rbp-416], -4294
mov BYTE PTR [rbp-1], 0
mov BYTE PTR [rbp-2], 0
mov BYTE PTR [rbp-9], 0
mov DWORD PTR [rbp-8], 0
jmp .L2
.L7:
mov eax, DWORD PTR [rbp-8]
cdqe
movzx eax, BYTE PTR [rbp-112+rax]
mov BYTE PTR [rbp-9], al
movzx eax, BYTE PTR [rbp-9]
cdqe
movzx eax, BYTE PTR [rbp-368+rax]
mov BYTE PTR [rbp-1], al
mov ecx, DWORD PTR [rbp-8]
movsx rax, ecx
imul rax, rax, 715827883
shr rax, 32
mov edx, eax
sar edx, 2
mov eax, ecx
sar eax, 31
sub edx, eax
mov eax, edx
add eax, eax
add eax, edx
sal eax, 3
sub ecx, eax
mov edx, ecx
movsx rax, edx
movzx eax, BYTE PTR [rbp-400+rax]
mov BYTE PTR [rbp-2], al
mov ecx, DWORD PTR [rbp-8]
movsx rax, ecx
imul rax, rax, 715827883
shr rax, 32
mov edx, eax
sar edx, 2
mov eax, ecx
sar eax, 31
sub edx, eax
mov eax, edx
add eax, eax
add eax, edx
sal eax, 3
sub ecx, eax
mov edx, ecx
mov eax, edx
and eax, 1
test eax, eax
je .L3
not BYTE PTR [rbp-2]
.L3:
movzx eax, BYTE PTR [rbp-2]
xor BYTE PTR [rbp-1], al
movzx eax, BYTE PTR [rbp-1]
cdqe
movzx eax, BYTE PTR [rbp-368+rax]
mov BYTE PTR [rbp-1], al
movzx eax, BYTE PTR [rbp-1]
and eax, 1
test eax, eax
je .L4
xor BYTE PTR [rbp-1], 66
.L4:
not BYTE PTR [rbp-1]
mov eax, DWORD PTR [rbp-8]
cdqe
movzx eax, BYTE PTR [rbp-464+rax]
cmp BYTE PTR [rbp-1], al
je .L5
mov edi, OFFSET FLAT:.LC2
mov eax, 0
call printf
mov eax, 1
jmp .L8
.L5:
add DWORD PTR [rbp-8], 1
.L2:
cmp DWORD PTR [rbp-8], 49
jle .L7
mov edi, OFFSET FLAT:.LC3
mov eax, 0
call printf
mov eax, 0
.L8:
leave
ret
Since the assembly code not too long we can reconstruct the code to another programming language such as python. Here is my implementation on python
from Crypto.Util.number import *
import string
def mov(addr, value, size):
value = value & (2**(size*8) - 1)
memory[addr:addr+size] = list(long_to_bytes(value)[::-1].rjust(size, b"\x00"))
def get(addr, size):
return bytes_to_long(bytes(memory[addr:addr+size]))
def not_op(value, size):
return ~value & (2**(size*8) - 1)
rbp = 500
memory = [0 for _ in range(1000)]
mov(rbp-112, 0, 8)
mov(rbp-104, 0, 8)
mov(rbp-96, 0, 8)
mov(rbp-88, 0, 8)
mov(rbp-80, 0, 8)
mov(rbp-72, 0, 8)
mov(rbp-64, 0, 8)
mov(rbp-56, 0, 8)
mov(rbp-48, 0, 8)
mov(rbp-40, 0, 8)
mov(rbp-32, 0, 8)
mov(rbp-24, 0, 8)
mov(rbp-16, 0, 8)
rax = 0xf3e8cbae4506845a
rdx = 0xd008415e3da6fe57
mov(rbp-368, rax, 8)
mov(rbp-360, rdx, 8)
rax = 0xa000dd2081212233
rdx = 0x1d18f58b0471af23
mov(rbp-352, rax, 8)
mov(rbp-344, rdx, 8)
rax = 0x3e7842ce09650fe1
rdx = 0xace032648fca37c3
mov(rbp-336, rax, 8)
mov(rbp-328, rdx, 8)
rax = 0x95f407c02a7c91de
rdx = 0x527ab667e553409f
mov(rbp-320, rax, 8)
mov(rbp-312, rdx, 8)
rax = 0x2e7282c94b833f4e
rdx = 0xc7d7b7cc1ef11c76
mov(rbp-304, rax, 8)
mov(rbp-296, rdx, 8)
rax = 0x1635194d1a79108a
rdx = 0x9244ab86cd2b437d
mov(rbp-288, rax, 8)
mov(rbp-280, rdx, 8)
rax = 0x24a79bb914980ed4
rdx = 0x4ffdf0d33ae23c1b
mov(rbp-272, rax, 8)
mov(rbp-264, rdx, 8)
rax = 0xda6a80480ca3d177
rdx = 0xec0b96fa5b47d8bd
mov(rbp-256, rax, 8)
mov(rbp-248, rdx, 8)
rax = 0xe727b17f11d949cf
rdx = 0x5db33628e663b2c5
mov(rbp-240, rax, 8)
mov(rbp-232, rdx, 8)
rax = 0x9cb0f62570a8dcfb
rdx = 0xfca985e439b85fa5
mov(rbp-224, rax, 8)
mov(rbp-216, rdx, 8)
rax = 0x74ff69f230510213
rdx = 0x6158c21746b559bf
mov(rbp-208, rax, 8)
mov(rbp-200, rdx, 8)
rax = 0xef6cee899ea4eb99
rdx = 0xdb6dbc548c7390a2
mov(rbp-192, rax, 8)
mov(rbp-184, rdx, 8)
rax = 0x34f7508da1e3d62c
rdx = 0x6b68be8e7b01f9d5
mov(rbp-176, rax, 8)
mov(rbp-168, rdx, 8)
rax = 0x1f15932fed2d9d55
rdx = 0x56ea5c0df8aa88c4
mov(rbp-160, rax, 8)
mov<