You only use strings command and check correct input.
It is similar to level 1.0
It is similar to level before; however, it swaps indexes '2' and '3'.
It don't show require, so I need to download file challenge and use IDA to read code.
read(0, &buf, 5uLL);
v3 = BYTE1(buf);
BYTE1(buf) = BYTE2(buf);
BYTE2(buf) = v3;
puts("Checking the received license key!\n");
if ( !memcmp(&buf, aEyfry, 5uLL) )
{
sub_12E9();
exit(0);
}
You can see that, it swaps indexes '1' and '2'.
-Using IDA or you can read instruction after run this challenge.
-In IDA:
for ( j = 0; j <= 1; ++j )
{
v3 = *((_BYTE *)&buf + j);
*((_BYTE *)&buf + j) = *((_BYTE *)&buf + 4 - j);
*((_BYTE *)&buf + 4 - j) = v3;
}
if ( !memcmp(&buf, EXPECTED_RESULT, 5uLL) )
{
win();
exit(0);
}
.data:0000000000004010 EXPECTED_RESULT db 'morjt',0 ; DATA XREF: main+2AF↑o
-So, you need to inpur tjrom
-It similar to level 3.0.
Use IDA to read key.
-Use IDA to read expected result:
for ( j = 0; j <= 4; ++j )
*((_BYTE *)&buf + j) ^= 0x88u;
-It seem that xor every digit in your input with 0x88.
-You need to reverse xor.
hex = [0xF8, 0xE2, 0xEE, 0xE0, 0xEC]
for i in range(len(hex)):
print(chr(hex[i] ^ 0x88), end='')
-Similar to 5.0
-I will start first at level 6.1 because it doesn't have command what challenge work in IDA
for ( i = 0; i <= 7; ++i )
{
v3 = *((_BYTE *)buf + i);
*((_BYTE *)buf + i) = *((_BYTE *)buf + 15 - i);
*((_BYTE *)buf + 15 - i) = v3;
}
for ( j = 0; j <= 15; ++j )
*((_BYTE *)buf + j) ^= 0x1Du;
for ( k = 0; k <= 15; ++k )
{
if ( k % 2 )
{
if ( k % 2 == 1 )
*((_BYTE *)buf + k) ^= 0xBAu;
}
else
{
*((_BYTE *)buf + k) ^= 0x5Eu;
}
}
-Look at this modification:
+In first loop from 0 to 7, it swap value at index i and index 15 - i.
+Xor all element with 0x1D
+Xor value at odd index with 0xBA and even index at 0x5E.
xor at index mod 3
for ( k = 0; k <= 24; ++k )
{
v3 = k % 3;
if ( k % 3 == 2 )
{
*((_BYTE *)&buf + k) ^= 0x13u;
}
else if ( v3 <= 2 )
{
if ( v3 )
{
if ( v3 == 1 )
*((_BYTE *)&buf + k) ^= 0xECu;
}
else
{
*((_BYTE *)&buf + k) ^= 0xA5u;
}
}
}
sort
for ( i = 0; i <= 23; ++i )
{
for ( j = 0; j < 24 - i; ++j )
{
if ( *((_BYTE *)&buf + j) > *((_BYTE *)&buf + j + 1) )
{
v7 = *((_BYTE *)&buf + j);
*((_BYTE *)&buf + j) = *((_BYTE *)&buf + j + 1);
*((_BYTE *)&buf + j + 1) = v7;
}
}
}
puts("Ready to receive your license key!\n");
read(0, &buf, 0x26uLL);
for ( i = 0; i <= 18; ++i )
{
v9 = *((_BYTE *)&buf + i);
*((_BYTE *)&buf + i) = *((_BYTE *)&buf + 37 - i);
*((_BYTE *)&buf + 37 - i) = v9;
}
for ( j = 0; j <= 18; ++j )
{
v8 = *((_BYTE *)&buf + j);
*((_BYTE *)&buf + j) = *((_BYTE *)&buf + 37 - j);
*((_BYTE *)&buf + 37 - j) = v8;
}
for ( k = 0; k <= 36; ++k )
{
for ( m = 0; m < 37 - k; ++m )
{
if ( *((_BYTE *)&buf + m) > *((_BYTE *)&buf + m + 1) )
{
v7 = *((_BYTE *)&buf + m);
*((_BYTE *)&buf + m) = *((_BYTE *)&buf + m + 1);
*((_BYTE *)&buf + m + 1) = v7;
}
}
}
v3 = BYTE5(v18);
BYTE5(v18) = BYTE4(v19);
BYTE4(v19) = v3;
for ( n = 0; n <= 18; ++n )
{
v6 = *((_BYTE *)&buf + n);
*((_BYTE *)&buf + n) = *((_BYTE *)&buf + 37 - n);
*((_BYTE *)&buf + 37 - n) = v6;
}
for ( ii = 0; ii <= 18; ++ii )
{
v5 = *((_BYTE *)&buf + ii);
*((_BYTE *)&buf + ii) = *((_BYTE *)&buf + 37 - ii);
*((_BYTE *)&buf + 37 - ii) = v5;
}
for ( jj = 0; jj <= 18; ++jj )
{
v4 = *((_BYTE *)&buf + jj);
*((_BYTE *)&buf + jj) = *((_BYTE *)&buf + 37 - jj);
*((_BYTE *)&buf + 37 - jj) = v4;
}
puts("Checking the received license key!\n");
if ( !memcmp(&buf, aZyxxuuuuutspon, 0x26uLL) )
{
sub_12E9();
exit(0);
}
puts("Wrong! No flag for you!");
exit(1);
}
-Read this code in IDA, you can see the step Sort.
-You only input your expected input and get the flag =)))
void __fastcall __noreturn main(int a1, char **a2, char **a3)
{
int v3; // eax
unsigned __int8 v4; // [rsp+2Dh] [rbp-B3h] BYREF
unsigned __int16 v5; // [rsp+2Eh] [rbp-B2h] BYREF
int v6; // [rsp+30h] [rbp-B0h]
int i; // [rsp+34h] [rbp-ACh]
unsigned __int64 v8; // [rsp+38h] [rbp-A8h]
char v9[96]; // [rsp+40h] [rbp-A0h] BYREF
__int64 v10[2]; // [rsp+A0h] [rbp-40h] BYREF
__int64 buf; // [rsp+B0h] [rbp-30h] BYREF
__int64 v12; // [rsp+B8h] [rbp-28h]
__int64 v13; // [rsp+C0h] [rbp-20h]
__int16 v14; // [rsp+C8h] [rbp-18h]
char v15; // [rsp+CAh] [rbp-16h]
unsigned __int64 v16; // [rsp+D8h] [rbp-8h]
v16 = __readfsqword(0x28u);
if ( a1 <= 0 )
__assert_fail("argc > 0", "<stdin>", 0x39u, "main");
puts("###");
printf("### Welcome to %s!\n", *a2);
puts("###");
putchar(10);
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 1uLL);
puts(
"This license verifier software will allow you to read the flag. However, before you can do so, you must verify that you");
puts("are licensed to read flag files! This program consumes a license key over stdin. Each program may perform entirely");
puts(
"different operations on that input! You must figure out (by reverse engineering this program) what that license key is.");
puts("Providing the correct license key will net you the flag!\n");
puts("Unfortunately for you, the license key cannot be reversed. You'll have to crack this program.\n");
v6 = 0;
v8 = ((unsigned __int64)sub_13A9 & 0xFFFFFFFFFFFFF000LL) - 4096;
do
v3 = v6++;
while ( !mprotect((void *)((v3 << 12) + v8), 0x1000uLL, 7) );
for ( i = 0; i <= 4; ++i )
{
printf("Changing byte %d/5.\n", (unsigned int)(i + 1));
printf("Offset (hex) to change: ");
__isoc99_scanf("%hx", &v5);
printf("New value (hex): ");
__isoc99_scanf("%hhx", &v4);
*(_BYTE *)(v5 + v8) = v4;
printf("The byte has been changed: *%p = %hhx.\n", (const void *)(v8 + v5), v4);
}
buf = 0LL;
v12 = 0LL;
v13 = 0LL;
v14 = 0;
v15 = 0;
puts("Ready to receive your license key!\n");
read(0, &buf, 0x1AuLL);
MD5_Init(v9);
MD5_Update(v9, &buf, 26LL);
MD5_Final(v10, v9);
memset(&buf, 0, 0x1AuLL);
buf = v10[0];
v12 = v10[1];
puts("Checking the received license key!\n");
if ( !memcmp(&buf, &unk_5010, 0x1AuLL) )
{
sub_1DAD();
exit(0);
}
puts("Wrong! No flag for you!");
exit(1);
}
Input
read(0, &buf, 0x1AuLL);
MD5_Init(v9);
MD5_Update(v9, &buf, 26LL);
MD5_Final(v10, v9);
memset(&buf, 0, 0x1AuLL);
buf = v10[0];
v12 = v10[1];
Option change value
*(_BYTE *)(v5 + v8) = v4;
0x555555555ed6: endbr64
0x555555555eda: push rbp
0x555555555edb: mov rbp,rsp
0x555555555ede: sub rsp,0xe0
0x555555555ee5: mov DWORD PTR [rbp-0xc4],edi
0x555555555eeb: mov QWORD PTR [rbp-0xd0],rsi
0x555555555ef2: mov QWORD PTR [rbp-0xd8],rdx
0x555555555ef9: mov rax,QWORD PTR fs:0x28
0x555555555f02: mov QWORD PTR [rbp-0x8],rax
0x555555555f06: xor eax,eax
0x555555555f08: cmp DWORD PTR [rbp-0xc4],0x0
0x555555555f0f: jg 0x555555555f30
0x555555555f11: lea rcx,[rip+0x14fc] # 0x555555557414
0x555555555f18: mov edx,0x39
0x555555555f1d: lea rsi,[rip+0x11e8] # 0x55555555710c
0x555555555f24: lea rdi,[rip+0x11e9] # 0x555555557114
0x555555555f2b: call 0x5555555551d0 <__assert_fail@plt>
0x555555555f30: lea rdi,[rip+0x11e6] # 0x55555555711d
0x555555555f37: call 0x5555555551b0 <puts@plt>
0x555555555f3c: mov rax,QWORD PTR [rbp-0xd0]
0x555555555f43: mov rax,QWORD PTR [rax]
0x555555555f46: mov rsi,rax
0x555555555f49: lea rdi,[rip+0x11d1] # 0x555555557121
0x555555555f50: mov eax,0x0
0x555555555f55: call 0x555555555190 <printf@plt>
0x555555555f5a: lea rdi,[rip+0x11bc] # 0x55555555711d
0x555555555f61: call 0x5555555551b0 <puts@plt>
0x555555555f66: mov edi,0xa
0x555555555f6b: call 0x5555555551f0 <putchar@plt>
0x555555555f70: mov rax,QWORD PTR [rip+0x30b9] # 0x555555559030 <stdin>
0x555555555f77: mov ecx,0x0
0x555555555f7c: mov edx,0x2
0x555555555f81: mov esi,0x0
0x555555555f86: mov rdi,rax
0x555555555f89: call 0x5555555551e0 <setvbuf@plt>
0x555555555f8e: mov rax,QWORD PTR [rip+0x30a3] # 0x555555559038 <stdout>
0x555555555f95: mov ecx,0x1
0x555555555f9a: mov edx,0x2
0x555555555f9f: mov esi,0x0
0x555555555fa4: mov rdi,rax
0x555555555fa7: call 0x5555555551e0 <setvbuf@plt>
0x555555555fac: lea rdi,[rip+0x1185] # 0x555555557138
0x555555555fb3: call 0x5555555551b0 <puts@plt>
0x555555555fb8: lea rdi,[rip+0x11f1] # 0x5555555571b0
0x555555555fbf: call 0x5555555551b0 <puts@plt>
0x555555555fc4: lea rdi,[rip+0x125d] # 0x555555557228
0x555555555fcb: call 0x5555555551b0 <puts@plt>
0x555555555fd0: lea rdi,[rip+0x12c9] # 0x5555555572a0
0x555555555fd7: call 0x5555555551b0 <puts@plt>
0x555555555fdc: lea rdi,[rip+0x12fd] # 0x5555555572e0
0x555555555fe3: call 0x5555555551b0 <puts@plt>
0x555555555fe8: mov DWORD PTR [rbp-0xb0],0x0
0x555555555ff2: lea rax,[rip+0xfffffffffffff3b0] # 0x5555555553a9
0x555555555ff9: and rax,0xfffffffffffff000
0x555555555fff: sub rax,0x1000
0x555555556005: mov QWORD PTR [rbp-0xa8],rax
0x55555555600c: nop
0x55555555600d: mov eax,DWORD PTR [rbp-0xb0]
0x555555556013: lea edx,[rax+0x1]
0x555555556016: mov DWORD PTR [rbp-0xb0],edx
0x55555555601c: shl eax,0xc
0x55555555601f: movsxd rdx,eax
0x555555556022: mov rax,QWORD PTR [rbp-0xa8]
0x555555556029: add rax,rdx
0x55555555602c: mov edx,0x7
0x555555556031: mov esi,0x1000
0x555555556036: mov rdi,rax
0x555555556039: call 0x555555555180 <mprotect@plt>
0x55555555603e: test eax,eax
0x555555556040: je 0x55555555600d
0x555555556042: mov DWORD PTR [rbp-0xac],0x0
0x55555555604c: jmp 0x55555555611f
0x555555556051: mov eax,DWORD PTR [rbp-0xac]
0x555555556057: add eax,0x1
0x55555555605a: mov esi,eax
0x55555555605c: lea rdi,[rip+0x12dc] # 0x55555555733f
0x555555556063: mov eax,0x0
0x555555556068: call 0x555555555190 <printf@plt>
0x55555555606d: lea rdi,[rip+0x12e0] # 0x555555557354
0x555555556074: mov eax,0x0
0x555555556079: call 0x555555555190 <printf@plt>
0x55555555607e: lea rax,[rbp-0xb2]
0x555555556085: mov rsi,rax
0x555555556088: lea rdi,[rip+0x12de] # 0x55555555736d
0x55555555608f: mov eax,0x0
0x555555556094: call 0x555555555280 <__isoc99_scanf@plt>
0x555555556099: lea rdi,[rip+0x12d1] # 0x555555557371
0x5555555560a0: mov eax,0x0
0x5555555560a5: call 0x555555555190 <printf@plt>
0x5555555560aa: lea rax,[rbp-0xb3]
0x5555555560b1: mov rsi,rax
0x5555555560b4: lea rdi,[rip+0x12c8] # 0x555555557383
0x5555555560bb: mov eax,0x0
0x5555555560c0: call 0x555555555280 <__isoc99_scanf@plt>
0x5555555560c5: movzx ecx,BYTE PTR [rbp-0xb3]
0x5555555560cc: movzx eax,WORD PTR [rbp-0xb2]
0x5555555560d3: movzx edx,ax
0x5555555560d6: mov rax,QWORD PTR [rbp-0xa8]
0x5555555560dd: add rax,rdx
0x5555555560e0: mov edx,ecx
0x5555555560e2: mov BYTE PTR [rax],dl
0x5555555560e4: movzx eax,BYTE PTR [rbp-0xb3]
0x5555555560eb: movzx eax,al
0x5555555560ee: movzx edx,WORD PTR [rbp-0xb2]
0x5555555560f5: movzx ecx,dx
0x5555555560f8: mov rdx,QWORD PTR [rbp-0xa8]
0x5555555560ff: add rcx,rdx
0x555555556102: mov edx,eax
0x555555556104: mov rsi,rcx
0x555555556107: lea rdi,[rip+0x127a] # 0x555555557388
0x55555555610e: mov eax,0x0
0x555555556113: call 0x555555555190 <printf@plt>
0x555555556118: add DWORD PTR [rbp-0xac],0x1
0x55555555611f: cmp DWORD PTR [rbp-0xac],0x4
0x555555556126: jle 0x555555556051
0x55555555612c: mov QWORD PTR [rbp-0x30],0x0
0x555555556134: mov QWORD PTR [rbp-0x28],0x0
0x55555555613c: mov QWORD PTR [rbp-0x20],0x0
0x555555556144: mov WORD PTR [rbp-0x18],0x0
0x55555555614a: mov BYTE PTR [rbp-0x16],0x0
0x55555555614e: lea rdi,[rip+0x125b] # 0x5555555573b0
0x555555556155: call 0x5555555551b0 <puts@plt>
0x55555555615a: lea rax,[rbp-0x30]
0x55555555615e: mov edx,0x1a
0x555555556163: mov rsi,rax
0x555555556166: mov edi,0x0
0x55555555616b: call 0x555555555200 <read@plt>
0x555555556170: lea rax,[rbp-0xa0]
0x555555556177: mov rdi,rax
0x55555555617a: call 0x555555555270 <MD5_Init@plt>
0x55555555617f: lea rcx,[rbp-0x30]
0x555555556183: lea rax,[rbp-0xa0]
0x55555555618a: mov edx,0x1a
0x55555555618f: mov rsi,rcx
0x555555556192: mov rdi,rax
0x555555556195: call 0x555555555230 <MD5_Update@plt>
0x55555555619a: lea rdx,[rbp-0xa0]
0x5555555561a1: lea rax,[rbp-0x40]
0x5555555561a5: mov rsi,rdx
0x5555555561a8: mov rdi,rax
0x5555555561ab: call 0x555555555220 <MD5_Final@plt>
0x5555555561b0: lea rax,[rbp-0x30]
0x5555555561b4: mov edx,0x1a
0x5555555561b9: mov esi,0x0
0x5555555561be: mov rdi,rax
0x5555555561c1: call 0x5555555551a0 <memset@plt>
0x5555555561c6: mov rax,QWORD PTR [rbp-0x40]
0x5555555561ca: mov rdx,QWORD PTR [rbp-0x38]
0x5555555561ce: mov QWORD PTR [rbp-0x30],rax
0x5555555561d2: mov QWORD PTR [rbp-0x28],rdx
0x5555555561d6: lea rdi,[rip+0x11fb] # 0x5555555573d8
0x5555555561dd: call 0x5555555551b0 <puts@plt>
0x5555555561e2: lea rax,[rbp-0x30]
0x5555555561e6: mov edx,0x1a
0x5555555561eb: lea rsi,[rip+0x2e1e] # 0x555555559010
0x5555555561f2: mov rdi,rax
0x5555555561f5: call 0x555555555290 <memcmp@plt>
0x5555555561fa: test eax,eax
0x5555555561fc: jne 0x555555556212
0x5555555561fe: mov eax,0x0
0x555555556203: call 0x555555555dad
0x555555556208: mov edi,0x0
0x55555555620d: call 0x5555555551c0 <exit@plt>
0x555555556212: lea rdi,[rip+0x11e3] # 0x5555555573fc
0x555555556219: call 0x5555555551b0 <puts@plt>
0x55555555621e: mov edi,0x1
0x555555556223: call 0x5555555551c0 <exit@plt>
The challenge allows me to change the value at the address starting from the address of v8.
It gives me five times to change one byte -> I can change a maximum 10 bytes; however, memcmp compares with the length of 0x1A. Therefore, the idea of changing my buf to a key value is impossible.
I see a special thing in IDA and when debugging.
!mprotect((void *)((v3 << 12) + v8), 0x1000uLL, 7)
jne: 75
je: 74
This challenge is similar to level 9
This challenge is to create two MD5 hashes and compare them together. Afterwards, it compares license key with my input.
Overwrite jne after memcmp two hashing values, and then input license key
It is different from level 11.0.
babyrev_level11.1
void __fastcall __noreturn main(int a1, char **a2, char **a3)
{
int v3; // eax
unsigned __int8 v4; // [rsp+25h] [rbp-DBh] BYREF
unsigned __int16 v5; // [rsp+26h] [rbp-DAh] BYREF
int v6; // [rsp+28h] [rbp-D8h]
int i; // [rsp+2Ch] [rbp-D4h]
int j; // [rsp+30h] [rbp-D0h]
int k; // [rsp+34h] [rbp-CCh]
unsigned __int64 v10; // [rsp+38h] [rbp-C8h]
char v11[96]; // [rsp+40h] [rbp-C0h] BYREF
char s1[16]; // [rsp+A0h] [rbp-60h] BYREF
char s2[16]; // [rsp+B0h] [rbp-50h] BYREF
__int64 v14[2]; // [rsp+C0h] [rbp-40h] BYREF
__int64 buf; // [rsp+D0h] [rbp-30h] BYREF
__int64 v16; // [rsp+D8h] [rbp-28h]
__int64 v17; // [rsp+E0h] [rbp-20h]
int v18; // [rsp+E8h] [rbp-18h]
__int16 v19; // [rsp+ECh] [rbp-14h]
unsigned __int64 v20; // [rsp+F8h] [rbp-8h]
v20 = __readfsqword(0x28u);
if ( a1 <= 0 )
__assert_fail("argc > 0", "<stdin>", 0x39u, "main");
puts("###");
printf("### Welcome to %s!\n", *a2);
puts("###");
putchar(10);
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 1uLL);
puts(
"This license verifier software will allow you to read the flag. However, before you can do so, you must verify that you");
puts("are licensed to read flag files! This program consumes a license key over stdin. Each program may perform entirely");
puts(
"different operations on that input! You must figure out (by reverse engineering this program) what that license key is.");
puts("Providing the correct license key will net you the flag!\n");
puts("Unfortunately for you, the license key cannot be reversed. You'll have to crack this program.\n");
v6 = 0;
v10 = ((unsigned __int64)sub_13A9 & 0xFFFFFFFFFFFFF000LL) - 4096;
do
v3 = v6++;
while ( !mprotect((void *)((v3 << 12) + v10), 0x1000uLL, 7) );
puts("In order to ensure code integrity, the code will be hashed and verified.\n");
MD5_Init(v11);
for ( i = 0; i < v6 - 1; ++i )
MD5_Update(v11, (i << 12) + v10, 4096LL);
MD5_Final(s1, v11);
for ( j = 0; j <= 1; ++j )
{
printf("Changing byte %d/2.\n", (unsigned int)(j + 1));
printf("Offset (hex) to change: ");
__isoc99_scanf("%hx", &v5);
printf("New value (hex): ");
__isoc99_scanf("%hhx", &v4);
*(_BYTE *)(v5 + v10) = v4;
printf("The byte has been changed: *%p = %hhx.\n", (const void *)(v10 + v5), v4);
}
MD5_Init(v11);
for ( k = 0; k < v6 - 1; ++k )
MD5_Update(v11, (k << 12) + v10, 4096LL);
MD5_Final(s2, v11);
if ( !memcmp(s1, s2, 0x10uLL) )
{
puts("The code's integrity is secure!\n");
buf = 0LL;
v16 = 0LL;
v17 = 0LL;
v18 = 0;
v19 = 0;
puts("Ready to receive your license key!\n");
read(0, &buf, 0x1DuLL);
MD5_Init(v11);
MD5_Update(v11, &buf, 29LL);
MD5_Final(v14, v11);
memset(&buf, 0, 0x1DuLL);
buf = v14[0];
v16 = v14[1];
puts("Checking the received license key!\n");
if ( !memcmp(&buf, &unk_4010, 0x1DuLL) )
{
sub_1923();
exit(0);
}
puts("Wrong! No flag for you!");
exit(1);
}
puts("The code's integrity has been breached, aborting!\n");
exit(1);
}
If you use the same approach as the before level in the first change, you will get the segmentation fault.
Solution
Online x86 / x64 Assembler and Disassembler
Thus, I try with je 0x44
Change the byte at 0x555555555db7 to 84.
Baby rev with a different layout.
execute_program
void __fastcall __noreturn execute_program(__int64 a1)
{
int v1; // eax
int v2; // eax
size_t v3; // rax
_BOOL4 v4; // [rsp+1Ch] [rbp-94h]
char buf[136]; // [rsp+20h] [rbp-90h] BYREF
unsigned __int64 v6; // [rsp+A8h] [rbp-8h]
v6 = __readfsqword(0x28u);
read(0, (void *)(a1 + 52), 8uLL);
interpret_imm(a1, 8LL, 84LL);
interpret_imm(a1, 32LL, 1LL);
interpret_imm(a1, 16LL, 16LL);
interpret_stm(a1, 8LL, 16LL);
interpret_add(a1, 8LL, 32LL);
interpret_imm(a1, 16LL, 86LL);
interpret_stm(a1, 8LL, 16LL);
interpret_add(a1, 8LL, 32LL);
interpret_imm(a1, 16LL, 249LL);
interpret_stm(a1, 8LL, 16LL);
interpret_add(a1, 8LL, 32LL);
interpret_imm(a1, 16LL, 132LL);
interpret_stm(a1, 8LL, 16LL);
interpret_add(a1, 8LL, 32LL);
interpret_imm(a1, 16LL, 94LL);
interpret_stm(a1, 8LL, 16LL);
interpret_add(a1, 8LL, 32LL);
interpret_imm(a1, 16LL, 213LL);
interpret_stm(a1, 8LL, 16LL);
interpret_add(a1, 8LL, 32LL);
interpret_imm(a1, 16LL, 216LL);
interpret_stm(a1, 8LL, 16LL);
interpret_add(a1, 8LL, 32LL);
interpret_imm(a1, 16LL, 16LL);
interpret_stm(a1, 8LL, 16LL);
interpret_add(a1, 8LL, 32LL);
v1 = memcmp((const void *)(a1 + 84), (const void *)(a1 + 52), 8uLL);
v4 = v1 == 0;
if ( v1 )
{
printf("INCORRECT!");
}
else
{
printf("CORRECT! Your flag: ");
v2 = open("/flag", 0);
v3 = read(v2, buf, 0x64uLL);
write(1, buf, v3);
}
exit(!v4);
}
describe_register
__int16 *__fastcall describe_register(char a1)
{
switch ( a1 )
{
case 16:
return aAbcdsif;
case 8:
return &aAbcdsif[1];
case 32:
return &aAbcdsif[2];
case 1:
return &aAbcdsif[3];
case 2:
return &aAbcdsif[4];
case 64:
return &aAbcdsif[5];
case 4:
return &aAbcdsif[6];
}
if ( a1 )
return (__int16 *)"?";
return (__int16 *)"NONE";
}
write_register
_BYTE *__fastcall write_register(_BYTE *a1, char a2, char a3)
{
_BYTE *result; // rax
switch ( a2 )
{
case 16:
result = a1;
a1[256] = a3;
break;
case 8:
result = a1;
a1[257] = a3;
break;
case 32:
result = a1;
a1[258] = a3;
break;
case 1:
result = a1;
a1[259] = a3;
break;
case 2:
result = a1;
a1[260] = a3;
break;
case 64:
result = a1;
a1[261] = a3;
break;
case 4:
result = a1;
a1[262] = a3;
break;
default:
crash(a1, "unknown register");
}
return result;
}
read_register
__int64 __fastcall read_register(unsigned __int8 *a1, char a2)
{
switch ( a2 )
{
case 16:
return a1[256];
case 8:
return a1[257];
case 32:
return a1[258];
case 1:
return a1[259];
case 2:
return a1[260];
case 64:
return a1[261];
}
if ( a2 != 4 )
crash(a1, "unknown register");
return a1[262];
}
write_memory
__int64 __fastcall write_memory(__int64 a1, unsigned __int8 a2, char a3)
{
__int64 result; // rax
result = a2;
*(_BYTE *)(a1 + a2) = a3;
return result;
}
interpret_imm
__int64 __fastcall interpret_imm(__int64 a1, unsigned __int8 a2, unsigned __int8 a3)
{
unsigned int v3; // ebx
const char *v4; // rax
v3 = a3;
v4 = (const char *)describe_register(a2);
printf("[s] IMM %s = %#hhx\n", v4, v3);
return write_register(a1, a2, a3);
}
interpret_stm
__int64 __fastcall interpret_stm(__int64 a1, unsigned __int8 a2, unsigned __int8 a3)
{
__int16 *v3; // rbx
__int16 *v4; // rax
unsigned __int8 v5; // al
v3 = describe_register(a3);
v4 = describe_register(a2);
printf("[s] STM *%s = %s\n", (const char *)v4, (const char *)v3);
LODWORD(v3) = (unsigned __int8)read_register(a1, a3);
v5 = read_register(a1, a2);
return write_memory(a1, v5, (unsigned int)v3);
}
a1[v5] = v3
interpret_add
_BYTE *__fastcall interpret_add(unsigned __int8 *a1, char a2, char a3)
{
__int16 *v3; // rbx
__int16 *v4; // rax
char v5; // al
v3 = describe_register(a3);
v4 = describe_register(a2);
printf("[s] ADD %s %s\n", (const char *)v4, (const char *)v3);
LOBYTE(v3) = read_register(a1, a2);
v5 = read_register(a1, a3);
return write_register(a1, a2, (unsigned __int8)v3 + v5);
}
Debug in gdb to get the informations and write them to script
In this level, it gives me one more function.
interpret_sys
int __fastcall interpret_sys(unsigned __int8 *a1, unsigned __int8 a2, unsigned __int8 a3)
{
const char *v3; // rax
unsigned __int8 v4; // al
unsigned __int64 v5; // rax
unsigned __int8 v6; // al
unsigned __int64 v7; // rax
unsigned __int8 v8; // al
unsigned __int8 v9; // al
int result; // eax
unsigned int v11; // ebx
const char *v12; // rax
v3 = (const char *)describe_register(a3);
printf("[s] SYS %#hhx %s\n", a2, v3);
if ( (a2 & 0x20) != 0 )
{
puts("[s] ... open");
v4 = sys_open(a1, &a1[a1[256]], a1[257], a1[258]);
write_register(a1, a3, v4);
}
if ( (a2 & 1) != 0 )
{
puts("[s] ... read_memory");
v5 = a1[258];
if ( 256 - a1[257] <= v5 )
LOBYTE(v5) = -a1[257];
v6 = sys_read(a1, a1[256], &a1[a1[257]], (unsigned __int8)v5);
write_register(a1, a3, v6);
}
if ( (a2 & 8) != 0 )
{
puts("[s] ... write");
v7 = a1[258];
if ( 256 - a1[257] <= v7 )
LOBYTE(v7) = -a1[257];
v8 = sys_write(a1, a1[256], &a1[a1[257]], (unsigned __int8)v7);
write_register(a1, a3, v8);
}
if ( (a2 & 4) != 0 )
{
puts("[s] ... sleep");
v9 = sys_sleep(a1, a1[256]);
write_register(a1, a3, v9);
}
result = a2 & 0x10;
if ( (a2 & 0x10) != 0 )
{
puts("[s] ... exit");
sys_exit(a1, a1[256]);
}
if ( a3 )
{
v11 = (unsigned __int8)read_register(a1, a3);
v12 = (const char *)describe_register(a3);
return printf("[s] ... return value (in register %s): %#hhx\n", v12, v11);
}
return result;
}
[s] ... read_memory
, so I only notice it.
if ( (a2 & 1) != 0 )
{
puts("[s] ... read_memory");
v5 = a1[258];
if ( 256 - a1[257] <= v5 )
LOBYTE(v5) = -a1[257];
v6 = sys_read(a1, a1[256], &a1[a1[257]], (unsigned __int8)v5);
write_register(a1, a3, v6);
}
ssize_t __fastcall sys_read(__int64 a1, int a2, void *a3, size_t a4)
{
return read(a2, a3, a4);
}
In this level, this function will take my input, whose length is v5(a1[258]) and save it into the array a1, from index 257.
execute_program
__int64 __fastcall execute_program(__int64 a1)
{
_BOOL4 v2; // [rsp+1Ch] [rbp-4h]
interpret_imm(a1, 1LL, 79LL);
interpret_imm(a1, 8LL, 8LL);
interpret_imm(a1, 64LL, 0LL);
interpret_sys(a1, 2LL, 64LL);
interpret_imm(a1, 1LL, 111LL);
interpret_imm(a1, 8LL, 1LL);
interpret_imm(a1, 64LL, 99LL);
interpret_stm(a1, 1LL, 64LL);
interpret_add(a1, 1LL, 8LL);
interpret_imm(a1, 64LL, 15LL);
interpret_stm(a1, 1LL, 64LL);
interpret_add(a1, 1LL, 8LL);
interpret_imm(a1, 64LL, 90LL);
interpret_stm(a1, 1LL, 64LL);
interpret_add(a1, 1LL, 8LL);
interpret_imm(a1, 64LL, 125LL);
interpret_stm(a1, 1LL, 64LL);
interpret_add(a1, 1LL, 8LL);
interpret_imm(a1, 64LL, 120LL);
interpret_stm(a1, 1LL, 64LL);
interpret_add(a1, 1LL, 8LL);
interpret_imm(a1, 64LL, 1LL);
interpret_stm(a1, 1LL, 64LL);
interpret_add(a1, 1LL, 8LL);
interpret_imm(a1, 64LL, 143LL);
interpret_stm(a1, 1LL, 64LL);
interpret_add(a1, 1LL, 8LL);
interpret_imm(a1, 64LL, 87LL);
interpret_stm(a1, 1LL, 64LL);
interpret_add(a1, 1LL, 8LL);
v2 = memcmp((const void *)(a1 + 111), (const void *)(a1 + 79), 8uLL) == 0;
interpret_imm(a1, 64LL, 1LL);
interpret_imm(a1, 1LL, 0LL);
interpret_imm(a1, 8LL, 1LL);
if ( v2 )
{
interpret_imm(a1, 2LL, 67LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 79LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 82LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 82LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 69LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 67LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 84LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 33LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 32LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 89LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 111LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 117LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 114LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 32LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 102LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 108LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 97LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 103LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 58LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 10LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 47LL);
interpret_imm(a1, 1LL, 0LL);
interpret_stm(a1, 1LL, 2LL);
interpret_imm(a1, 2LL, 102LL);
interpret_imm(a1, 1LL, 1LL);
interpret_stm(a1, 1LL, 2LL);
interpret_imm(a1, 2LL, 108LL);
interpret_imm(a1, 1LL, 2LL);
interpret_stm(a1, 1LL, 2LL);
interpret_imm(a1, 2LL, 97LL);
interpret_imm(a1, 1LL, 3LL);
interpret_stm(a1, 1LL, 2LL);
interpret_imm(a1, 2LL, 103LL);
interpret_imm(a1, 1LL, 4LL);
interpret_stm(a1, 1LL, 2LL);
interpret_imm(a1, 2LL, 0LL);
interpret_imm(a1, 1LL, 5LL);
interpret_stm(a1, 1LL, 2LL);
interpret_imm(a1, 64LL, 0LL);
interpret_imm(a1, 1LL, 0LL);
interpret_sys(a1, 32LL, 64LL);
interpret_imm(a1, 8LL, 100LL);
interpret_sys(a1, 2LL, 8LL);
interpret_imm(a1, 64LL, 1LL);
interpret_sys(a1, 8LL, 8LL);
interpret_imm(a1, 64LL, 0LL);
}
else
{
interpret_imm(a1, 2LL, 73LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 78LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 67LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 79LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 82LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 82LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 69LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 67LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 84LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 2LL, 33LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
interpret_imm(a1, 64LL, 1LL);
}
interpret_imm(a1, 2LL, 10LL);
interpret_stm(a1, 1LL, 2LL);
interpret_sys(a1, 8LL, 64LL);
return interpret_sys(a1, 16LL, 64LL);
}
v2 != 0
to get the flag.The difference between this level and the previous level is that function interpret_sys has options [s] ... write
and [s] ... exit
if ( (a2 & 0x10) != 0 )
{
puts("[s] ... exit");
exit(a1[256]);
}
if ( (a2 & 8) != 0 )
{
puts("[s] ... write");
v7 = a1[258];
if ( 256 - a1[257] <= v7 )
LOBYTE(v7) = -a1[257];
v8 = write(a1[256], &a1[a1[257]], (unsigned __int8)v7);
write_register(a1, a3, v8);
}
In this level, we have two more functions.
interpret_ldm
_BYTE *__fastcall interpret_ldm(unsigned __int8 *a1, char a2, char a3)
{
__int16 *v3; // rbx
__int16 *v4; // rax
unsigned __int8 v5; // al
char memory; // al
v3 = describe_register(a3);
v4 = describe_register(a2);
printf("[s] LDM %s = *%s\n", (const char *)v4, (const char *)v3);
v5 = read_register(a1, a3);
memory = read_memory((__int64)a1, v5);
return write_register(a1, a2, memory);
}
interpret_cmp
unsigned __int64 __fastcall interpret_cmp(unsigned __int8 *a1, char a2, char a3)
{
__int16 *v3; // rbx
__int16 *v4; // rax
unsigned __int64 result; // rax
unsigned __int8 v7; // [rsp+1Eh] [rbp-12h]
unsigned __int8 v8; // [rsp+1Fh] [rbp-11h]
v3 = describe_register(a3);
v4 = describe_register(a2);
printf("[s] CMP %s %s\n", (const char *)v4, (const char *)v3);
v7 = read_register(a1, a2);
v8 = read_register(a1, a3);
a1[262] = 0;
if ( v7 < v8 )
a1[262] |= 2u;
if ( v7 > v8 )
a1[262] |= 4u;
if ( v7 == v8 )
a1[262] |= 0x10u;
result = v7;
if ( v7 != v8 )
{
result = (unsigned __int64)a1;
a1[262] |= 1u;
}
if ( !v7 && !v8 )
{
result = (unsigned __int64)a1;
a1[262] |= 8u;
}
return result;
}
execute_program
int __fastcall execute_program(unsigned __int8 *a1)
{
_BOOL4 v2; // [rsp+1Ch] [rbp-4h]
interpret_imm((__int64)a1, 0x10u, 0x73u);
interpret_imm((__int64)a1, 1u, 8u);
interpret_imm((__int64)a1, 0x20u, 0);
interpret_sys(a1, 0x20u, 0x20u);
interpret_imm((__int64)a1, 0x10u, 0x93u);
interpret_imm((__int64)a1, 1u, 1u);
interpret_imm((__int64)a1, 0x20u, 0xB2u);
interpret_stm(a1, 16LL, 32LL);
interpret_add(a1, 0x10u, 1u);
interpret_imm((__int64)a1, 0x20u, 0x8Au);
interpret_stm(a1, 16LL, 32LL);
interpret_add(a1, 0x10u, 1u);
interpret_imm((__int64)a1, 0x20u, 0x6Eu);
interpret_stm(a1, 16LL, 32LL);
interpret_add(a1, 0x10u, 1u);
interpret_imm((__int64)a1, 0x20u, 0x5Au);
interpret_stm(a1, 16LL, 32LL);
interpret_add(a1, 0x10u, 1u);
interpret_imm((__int64)a1, 0x20u, 0xAFu);
interpret_stm(a1, 16LL, 32LL);
interpret_add(a1, 0x10u, 1u);
interpret_imm((__int64)a1, 0x20u, 0x33u);
interpret_stm(a1, 16LL, 32LL);
interpret_add(a1, 0x10u, 1u);
interpret_imm((__int64)a1, 0x20u, 0xE9u);
interpret_stm(a1, 16LL, 32LL);
interpret_add(a1, 0x10u, 1u);
interpret_imm((__int64)a1, 0x20u, 0xB9u);
interpret_stm(a1, 16LL, 32LL);
interpret_add(a1, 0x10u, 1u);
interpret_imm((__int64)a1, 0x10u, 0x93u);
interpret_ldm(a1, 16, 16);
interpret_imm((__int64)a1, 0x20u, 0x73u);
interpret_ldm(a1, 32, 32);
interpret_cmp(a1, 32, 16);
v2 = (a1[262] & 0x10) != 0;
interpret_imm((__int64)a1, 0x10u, 0x94u);
interpret_ldm(a1, 16, 16);
interpret_imm((__int64)a1, 0x20u, 0x74u);
interpret_ldm(a1, 32, 32);
interpret_cmp(a1, 32, 16);
if ( (a1[262] & 0x10) == 0 )
v2 = 0;
interpret_imm((__int64)a1, 0x10u, 0x95u);
interpret_ldm(a1, 16, 16);
interpret_imm((__int64)a1, 0x20u, 0x75u);
interpret_ldm(a1, 32, 32);
interpret_cmp(a1, 32, 16);
if ( (a1[262] & 0x10) == 0 )
v2 = 0;
interpret_imm((__int64)a1, 0x10u, 0x96u);
interpret_ldm(a1, 16, 16);
interpret_imm((__int64)a1, 0x20u, 0x76u);
interpret_ldm(a1, 32, 32);
interpret_cmp(a1, 32, 16);
if ( (a1[262] & 0x10) == 0 )
v2 = 0;
interpret_imm((__int64)a1, 0x10u, 0x97u);
interpret_ldm(a1, 16, 16);
interpret_imm((__int64)a1, 0x20u, 0x77u);
interpret_ldm(a1, 32, 32);
interpret_cmp(a1, 32, 16);
if ( (a1[262] & 0x10) == 0 )
v2 = 0;
interpret_imm((__int64)a1, 0x10u, 0x98u);
interpret_ldm(a1, 16, 16);
interpret_imm((__int64)a1, 0x20u, 0x78u);
interpret_ldm(a1, 32, 32);
interpret_cmp(a1, 32, 16);
if ( (a1[262] & 0x10) == 0 )
v2 = 0;
interpret_imm((__int64)a1, 0x10u, 0x99u);
interpret_ldm(a1, 16, 16);
interpret_imm((__int64)a1, 0x20u, 0x79u);
interpret_ldm(a1, 32, 32);
interpret_cmp(a1, 32, 16);
if ( (a1[262] & 0x10) == 0 )
v2 = 0;
interpret_imm((__int64)a1, 0x10u, 0x9Au);
interpret_ldm(a1, 16, 16);
interpret_imm((__int64)a1, 0x20u, 0x7Au);
interpret_ldm(a1, 32, 32);
interpret_cmp(a1, 32, 16);
if ( (a1[262] & 0x10) == 0 )
v2 = 0;
interpret_imm((__int64)a1, 0x20u, 1u);
interpret_imm((__int64)a1, 0x10u, 0);
interpret_imm((__int64)a1, 1u, 1u);
if ( v2 )
{
interpret_imm((__int64)a1, 8u, 0x43u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x4Fu);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x52u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x52u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x45u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x43u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x54u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x21u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x20u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x59u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x6Fu);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x75u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x72u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x20u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x66u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x6Cu);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x61u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x67u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x3Au);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0xAu);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x2Fu);
interpret_imm((__int64)a1, 0x10u, 0);
interpret_stm(a1, 16LL, 8LL);
interpret_imm((__int64)a1, 8u, 0x66u);
interpret_imm((__int64)a1, 0x10u, 1u);
interpret_stm(a1, 16LL, 8LL);
interpret_imm((__int64)a1, 8u, 0x6Cu);
interpret_imm((__int64)a1, 0x10u, 2u);
interpret_stm(a1, 16LL, 8LL);
interpret_imm((__int64)a1, 8u, 0x61u);
interpret_imm((__int64)a1, 0x10u, 3u);
interpret_stm(a1, 16LL, 8LL);
interpret_imm((__int64)a1, 8u, 0x67u);
interpret_imm((__int64)a1, 0x10u, 4u);
interpret_stm(a1, 16LL, 8LL);
interpret_imm((__int64)a1, 8u, 0);
interpret_imm((__int64)a1, 0x10u, 5u);
interpret_stm(a1, 16LL, 8LL);
interpret_imm((__int64)a1, 0x20u, 0);
interpret_imm((__int64)a1, 0x10u, 0);
interpret_sys(a1, 8u, 0x20u);
interpret_imm((__int64)a1, 1u, 0x64u);
interpret_sys(a1, 0x20u, 1u);
interpret_imm((__int64)a1, 0x20u, 1u);
interpret_sys(a1, 2u, 1u);
interpret_imm((__int64)a1, 0x20u, 0);
}
else
{
interpret_imm((__int64)a1, 8u, 0x49u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x4Eu);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x43u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x4Fu);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x52u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x52u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x45u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x43u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x54u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 8u, 0x21u);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
interpret_imm((__int64)a1, 0x20u, 1u);
}
interpret_imm((__int64)a1, 8u, 0xAu);
interpret_stm(a1, 16LL, 8LL);
interpret_sys(a1, 2u, 0x20u);
return interpret_sys(a1, 1u, 0x20u);
}
I notice the special execute_program
interpret_ldm(a1, 16, 16);
interpret_ldm(a1, 32, 32);
I will get the first stage to explain
#save the value at the third agrument to a1[257]
interpret_imm(a1, 0x10, 0x93)
#read the value at a1[257], after which make it an index to read at this index and store it at a1[257]
# index = a1[257]
# a1[257] = a1[index]
interpret_ldm(a1, 16, 16)
#save the value at the third agrument to a1[256]
interpret_imm(a1, 0x20, 0x73)
#read the value at a1[256], after which make it an index to read at this index and store it at a1[256]
# index = a1[256]
# a1[256] = a1[index]
interpret_ldm(a1, 32, 32)
#compare the value between a1[256] and a1[257]
interpret_cmp(a1, 32, 16)
In the other stage, the value of the the third agrument in function interpret_imm increase from 0x94 → 0x9A and from 0x74 → 0x7A
To get the flag, I need to have make v2 != 0
a1[256] = a1[257]
After this level makes a license key, it has the value at index 0x94 → 0x9A. I can get them by reversing. And the value 0x74 → 0x7A is my input.
__int64 __fastcall interpret_stm(unsigned __int8 *a1, char a2, char a3)
{
__int16 *v3; // rbx
__int16 *v4; // rax
unsigned __int8 v5; // al
v3 = describe_register(a3);
v4 = describe_register(a2);
printf("[s] STM *%s = %s\n", (const char *)v4, (const char *)v3);
LOBYTE(v3) = read_register(a1, a3);
v5 = read_register(a1, a2);
return write_memory((__int64)a1, v5, (char)v3);
}
return write_memory((__int64)a1, v5, (char)v3);
So, let's modify the script a little
execute_program
__int64 __fastcall sub_198C(_BYTE *a1)
{
_BOOL4 v2; // [rsp+1Ch] [rbp-4h]
interpret_imm(a1, 4, 53);
interpret_imm(a1, 16, 6);
interpret_imm(a1, 2, 0);
interpret_sys(a1, 16LL, 2LL);
interpret_imm(a1, 4, 85);
interpret_imm(a1, 16, 1);
interpret_imm(a1, 2, 212);
interpret_stm(a1, 4LL, 2LL);
interpret_add(a1, 4LL, 16LL);
interpret_imm(a1, 2, 29);
interpret_stm(a1, 4LL, 2LL);
interpret_add(a1, 4LL, 16LL);
interpret_imm(a1, 2, 121);
interpret_stm(a1, 4LL, 2LL);
interpret_add(a1, 4LL, 16LL);
interpret_imm(a1, 2, 68);
interpret_stm(a1, 4LL, 2LL);
interpret_add(a1, 4LL, 16LL);
interpret_imm(a1, 2, 42);
interpret_stm(a1, 4LL, 2LL);
interpret_add(a1, 4LL, 16LL);
interpret_imm(a1, 2, 204);
interpret_stm(a1, 4LL, 2LL);
interpret_add(a1, 4LL, 16LL);
interpret_imm(a1, 4, 53);
interpret_imm(a1, 16, 1);
interpret_ldm((__int64)a1, 2u, 4u);
interpret_imm(a1, 32, 110);
interpret_add(a1, 2LL, 32LL);
interpret_stm(a1, 4LL, 2LL);
interpret_add(a1, 4LL, 16LL);
interpret_ldm((__int64)a1, 2u, 4u);
interpret_imm(a1, 32, 211);
interpret_add(a1, 2LL, 32LL);
interpret_stm(a1, 4LL, 2LL);
interpret_add(a1, 4LL, 16LL);
interpret_ldm((__int64)a1, 2u, 4u);
interpret_imm(a1, 32, 253);
interpret_add(a1, 2LL, 32LL);
interpret_stm(a1, 4LL, 2LL);
interpret_add(a1, 4LL, 16LL);
interpret_ldm((__int64)a1, 2u, 4u);
interpret_imm(a1, 32, 140);
interpret_add(a1, 2LL, 32LL);
interpret_stm(a1, 4LL, 2LL);
interpret_add(a1, 4LL, 16LL);
interpret_ldm((__int64)a1, 2u, 4u);
interpret_imm(a1, 32, 165);
interpret_add(a1, 2LL, 32LL);
interpret_stm(a1, 4LL, 2LL);
interpret_add(a1, 4LL, 16LL);
interpret_ldm((__int64)a1, 2u, 4u);
interpret_imm(a1, 32, 215);
interpret_add(a1, 2LL, 32LL);
interpret_stm(a1, 4LL, 2LL);
interpret_add(a1, 4LL, 16LL);
interpret_imm(a1, 4, 85);
interpret_ldm((__int64)a1, 4u, 4u);
interpret_imm(a1, 2, 53);
interpret_ldm((__int64)a1, 2u, 2u);
interpret_cmp(a1, 2LL, 4LL);
v2 = (a1[262] & 4) != 0;
interpret_imm(a1, 4, 86);
interpret_ldm((__int64)a1, 4u, 4u);
interpret_imm(a1, 2, 54);
interpret_ldm((__int64)a1, 2u, 2u);
interpret_cmp(a1, 2LL, 4LL);
if ( (a1[262] & 4) == 0 )
v2 = 0;
interpret_imm(a1, 4, 87);
interpret_ldm((__int64)a1, 4u, 4u);
interpret_imm(a1, 2, 55);
interpret_ldm((__int64)a1, 2u, 2u);
interpret_cmp(a1, 2LL, 4LL);
if ( (a1[262] & 4) == 0 )
v2 = 0;
interpret_imm(a1, 4, 88);
interpret_ldm((__int64)a1, 4u, 4u);
interpret_imm(a1, 2, 56);
interpret_ldm((__int64)a1, 2u, 2u);
interpret_cmp(a1, 2LL, 4LL);
if ( (a1[262] & 4) == 0 )
v2 = 0;
interpret_imm(a1, 4, 89);
interpret_ldm((__int64)a1, 4u, 4u);
interpret_imm(a1, 2, 57);
interpret_ldm((__int64)a1, 2u, 2u);
interpret_cmp(a1, 2LL, 4LL);
if ( (a1[262] & 4) == 0 )
v2 = 0;
interpret_imm(a1, 4, 90);
interpret_ldm((__int64)a1, 4u, 4u);
interpret_imm(a1, 2, 58);
interpret_ldm((__int64)a1, 2u, 2u);
interpret_cmp(a1, 2LL, 4LL);
if ( (a1[262] & 4) == 0 )
v2 = 0;
interpret_imm(a1, 2, 1);
interpret_imm(a1, 4, 0);
interpret_imm(a1, 16, 1);
if ( v2 )
{
interpret_imm(a1, 32, 67);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 79);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 82);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 82);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 69);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 67);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 84);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 33);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 32);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 89);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 111);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 117);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 114);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 32);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 102);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 108);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 97);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 103);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 58);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 10);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 47);
interpret_imm(a1, 4, 0);
interpret_stm(a1, 4LL, 32LL);
interpret_imm(a1, 32, 102);
interpret_imm(a1, 4, 1);
interpret_stm(a1, 4LL, 32LL);
interpret_imm(a1, 32, 108);
interpret_imm(a1, 4, 2);
interpret_stm(a1, 4LL, 32LL);
interpret_imm(a1, 32, 97);
interpret_imm(a1, 4, 3);
interpret_stm(a1, 4LL, 32LL);
interpret_imm(a1, 32, 103);
interpret_imm(a1, 4, 4);
interpret_stm(a1, 4LL, 32LL);
interpret_imm(a1, 32, 0);
interpret_imm(a1, 4, 5);
interpret_stm(a1, 4LL, 32LL);
interpret_imm(a1, 2, 0);
interpret_imm(a1, 4, 0);
interpret_sys(a1, 1LL, 2LL);
interpret_imm(a1, 16, 100);
interpret_sys(a1, 16LL, 16LL);
interpret_imm(a1, 2, 1);
interpret_sys(a1, 4LL, 16LL);
interpret_imm(a1, 2, 0);
}
else
{
interpret_imm(a1, 32, 73);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 78);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 67);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 79);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 82);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 82);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 69);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 67);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 84);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 32, 33);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
interpret_imm(a1, 2, 1);
}
interpret_imm(a1, 32, 10);
interpret_stm(a1, 4LL, 32LL);
interpret_sys(a1, 4LL, 2LL);
return interpret_sys(a1, 32LL, 2LL);
}
*It is similar to level 17.0; however, it has some differences
In some functions, the type of agrument is char
interpret_add(unsigned __int8 *a1, char a2, char a3)
interpret_ldm(unsigned __int8 *a1, char a2, char a3)
interpret_cmp(unsigned __int8 *a1, char a2, char a3)
From line 5 to line 31: create license key or do something.
In the next every stage, I notice that there is some similar region. I will take one of them to explain(my input is abcdef)
interpret_imm(a1, 32, 110); // a1[259] = 110
interpret_add(a1, 2LL, 32LL); // a1[256] = a1[256] + a1[259]
interpret_stm(a1, 4LL, 2LL); // a1[a1[257]] = a1[256]
interpret_add(a1, 4LL, 16LL); // a1[257] = a1[257] + a1[258]
interpret_ldm((__int64)a1, 2u, 4u); // a1[256] = a1[a1[257]]
Overall, it takes each bytes in my input and increases or decreases with the specified value.
execute_program
__int64 __fastcall execute_program(__int64 a1)
{
_BOOL4 v2; // [rsp+1Ch] [rbp-4h]
interpret_imm(a1, 4LL, 96LL);
interpret_imm(a1, 1LL, 9LL);
interpret_imm(a1, 32LL, 0LL);
interpret_sys(a1, 2LL, 32LL);
interpret_imm(a1, 4LL, 128LL);
interpret_imm(a1, 1LL, 1LL);
interpret_imm(a1, 32LL, 65LL);
interpret_stm(a1, 4LL, 32LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 87LL);
interpret_stm(a1, 4LL, 32LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 208LL);
interpret_stm(a1, 4LL, 32LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 192LL);
interpret_stm(a1, 4LL, 32LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 159LL);
interpret_stm(a1, 4LL, 32LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 211LL);
interpret_stm(a1, 4LL, 32LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 236LL);
interpret_stm(a1, 4LL, 32LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 57LL);
interpret_stm(a1, 4LL, 32LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 65LL);
interpret_stm(a1, 4LL, 32LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 4LL, 128LL);
interpret_ldm(a1, 4LL, 4LL);
interpret_imm(a1, 1LL, 38LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 96LL);
interpret_ldm(a1, 32LL, 32LL);
interpret_cmp(a1, 32LL, 4LL);
v2 = (*(_BYTE *)(a1 + 262) & 0x10) != 0;
interpret_imm(a1, 4LL, 129LL);
interpret_ldm(a1, 4LL, 4LL);
interpret_imm(a1, 1LL, 224LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 97LL);
interpret_ldm(a1, 32LL, 32LL);
interpret_cmp(a1, 32LL, 4LL);
if ( (*(_BYTE *)(a1 + 262) & 0x10) == 0 )
v2 = 0;
interpret_imm(a1, 4LL, 130LL);
interpret_ldm(a1, 4LL, 4LL);
interpret_imm(a1, 1LL, 194LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 98LL);
interpret_ldm(a1, 32LL, 32LL);
interpret_cmp(a1, 32LL, 4LL);
if ( (*(_BYTE *)(a1 + 262) & 0x10) == 0 )
v2 = 0;
interpret_imm(a1, 4LL, 131LL);
interpret_ldm(a1, 4LL, 4LL);
interpret_imm(a1, 1LL, 77LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 99LL);
interpret_ldm(a1, 32LL, 32LL);
interpret_cmp(a1, 32LL, 4LL);
if ( (*(_BYTE *)(a1 + 262) & 0x10) == 0 )
v2 = 0;
interpret_imm(a1, 4LL, 132LL);
interpret_ldm(a1, 4LL, 4LL);
interpret_imm(a1, 1LL, 76LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 100LL);
interpret_ldm(a1, 32LL, 32LL);
interpret_cmp(a1, 32LL, 4LL);
if ( (*(_BYTE *)(a1 + 262) & 0x10) == 0 )
v2 = 0;
interpret_imm(a1, 4LL, 133LL);
interpret_ldm(a1, 4LL, 4LL);
interpret_imm(a1, 1LL, 59LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 101LL);
interpret_ldm(a1, 32LL, 32LL);
interpret_cmp(a1, 32LL, 4LL);
if ( (*(_BYTE *)(a1 + 262) & 0x10) == 0 )
v2 = 0;
interpret_imm(a1, 4LL, 134LL);
interpret_ldm(a1, 4LL, 4LL);
interpret_imm(a1, 1LL, 120LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 102LL);
interpret_ldm(a1, 32LL, 32LL);
interpret_cmp(a1, 32LL, 4LL);
if ( (*(_BYTE *)(a1 + 262) & 0x10) == 0 )
v2 = 0;
interpret_imm(a1, 4LL, 135LL);
interpret_ldm(a1, 4LL, 4LL);
interpret_imm(a1, 1LL, 142LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 103LL);
interpret_ldm(a1, 32LL, 32LL);
interpret_cmp(a1, 32LL, 4LL);
if ( (*(_BYTE *)(a1 + 262) & 0x10) == 0 )
v2 = 0;
interpret_imm(a1, 4LL, 136LL);
interpret_ldm(a1, 4LL, 4LL);
interpret_imm(a1, 1LL, 131LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 104LL);
interpret_ldm(a1, 32LL, 32LL);
interpret_cmp(a1, 32LL, 4LL);
if ( (*(_BYTE *)(a1 + 262) & 0x10) == 0 )
v2 = 0;
interpret_imm(a1, 32LL, 1LL);
interpret_imm(a1, 4LL, 0LL);
interpret_imm(a1, 1LL, 1LL);
if ( v2 )
{
interpret_imm(a1, 16LL, 67LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 79LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 82LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 82LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 69LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 67LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 84LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 33LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 32LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 89LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 111LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 117LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 114LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 32LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 102LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 108LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 97LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 103LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 58LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 10LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 47LL);
interpret_imm(a1, 4LL, 0LL);
interpret_stm(a1, 4LL, 16LL);
interpret_imm(a1, 16LL, 102LL);
interpret_imm(a1, 4LL, 1LL);
interpret_stm(a1, 4LL, 16LL);
interpret_imm(a1, 16LL, 108LL);
interpret_imm(a1, 4LL, 2LL);
interpret_stm(a1, 4LL, 16LL);
interpret_imm(a1, 16LL, 97LL);
interpret_imm(a1, 4LL, 3LL);
interpret_stm(a1, 4LL, 16LL);
interpret_imm(a1, 16LL, 103LL);
interpret_imm(a1, 4LL, 4LL);
interpret_stm(a1, 4LL, 16LL);
interpret_imm(a1, 16LL, 0LL);
interpret_imm(a1, 4LL, 5LL);
interpret_stm(a1, 4LL, 16LL);
interpret_imm(a1, 32LL, 0LL);
interpret_imm(a1, 4LL, 0LL);
interpret_sys(a1, 1LL, 32LL);
interpret_imm(a1, 1LL, 100LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 32LL, 1LL);
interpret_sys(a1, 16LL, 1LL);
interpret_imm(a1, 32LL, 0LL);
}
else
{
interpret_imm(a1, 16LL, 73LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 78LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 67LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 79LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 82LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 82LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 69LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 67LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 84LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 16LL, 33LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
interpret_imm(a1, 32LL, 1LL);
}
interpret_imm(a1, 16LL, 10LL);
interpret_stm(a1, 4LL, 16LL);
interpret_sys(a1, 16LL, 32LL);
return interpret_sys(a1, 8LL, 32LL);
}
The first part
interpret_imm(a1, 4LL, 128LL);
interpret_ldm(a1, 4LL, 4LL);
interpret_imm(a1, 1LL, 38LL);
interpret_add(a1, 4LL, 1LL);
interpret_imm(a1, 32LL, 96LL);
interpret_ldm(a1, 32LL, 32LL);
interpret_cmp(a1, 32LL, 4LL);
It does
//a1[257] = 128
interpret_imm(a1, 4, 128)
//index = a1[257] (=128)
//a1[257] = a1[index]
interpret_ldm(a1, 4, 4)
//a1[258] = 38
interpret_imm(a1, 1, 38)
//a1[257] += a1[258]
interpret_add(a1, 4, 1)
//a1[256] = 96
interpret_imm(a1, 32, 96)
//index = a1[256]
//memory = a1[index]
//a1[256] = memory
// ~~~ a1[256] = a1[96]
interpret_ldm(a1, 32, 32)
//compare a1[256] and a1[257]
interpret_cmp(a1, 32, 4)
execute_program
__int64 __fastcall sub_198C(_BYTE *a1)
{
_BOOL4 v2; // [rsp+1Ch] [rbp-4h]
interpret_imm(a1, 32, 96);
interpret_imm(a1, 16, 12);
interpret_imm(a1, 1, 0);
interpret_sys(a1, 32LL, 1LL);
interpret_imm(a1, 32, 128);
interpret_imm(a1, 16, 1);
interpret_imm(a1, 1, 170);
interpret_stm(a1, 32LL, 1LL);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 150);
interpret_stm(a1, 32LL, 1LL);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 100);
interpret_stm(a1, 32LL, 1LL);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 106);
interpret_stm(a1, 32LL, 1LL);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 11);
interpret_stm(a1, 32LL, 1LL);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 238);
interpret_stm(a1, 32LL, 1LL);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 101);
interpret_stm(a1, 32LL, 1LL);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 9);
interpret_stm(a1, 32LL, 1LL);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 168);
interpret_stm(a1, 32LL, 1LL);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 33);
interpret_stm(a1, 32LL, 1LL);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 105);
interpret_stm(a1, 32LL, 1LL);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 8);
interpret_stm(a1, 32LL, 1LL);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 32, 128);
interpret_ldm(a1, 32LL, 32LL);
interpret_imm(a1, 16, 17);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 96);
interpret_ldm(a1, 1LL, 1LL);
interpret_cmp(a1, 1LL, 32LL);
v2 = (a1[262] & 2) != 0;
interpret_imm(a1, 32, 129);
interpret_ldm(a1, 32LL, 32LL);
interpret_imm(a1, 16, 1);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 97);
interpret_ldm(a1, 1LL, 1LL);
interpret_cmp(a1, 1LL, 32LL);
if ( (a1[262] & 2) == 0 )
v2 = 0;
interpret_imm(a1, 32, 130);
interpret_ldm(a1, 32LL, 32LL);
interpret_imm(a1, 16, 203);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 98);
interpret_ldm(a1, 1LL, 1LL);
interpret_cmp(a1, 1LL, 32LL);
if ( (a1[262] & 2) == 0 )
v2 = 0;
interpret_imm(a1, 32, 131);
interpret_ldm(a1, 32LL, 32LL);
interpret_imm(a1, 16, 195);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 99);
interpret_ldm(a1, 1LL, 1LL);
interpret_cmp(a1, 1LL, 32LL);
if ( (a1[262] & 2) == 0 )
v2 = 0;
interpret_imm(a1, 32, 132);
interpret_ldm(a1, 32LL, 32LL);
interpret_imm(a1, 16, 148);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 100);
interpret_ldm(a1, 1LL, 1LL);
interpret_cmp(a1, 1LL, 32LL);
if ( (a1[262] & 2) == 0 )
v2 = 0;
interpret_imm(a1, 32, 133);
interpret_ldm(a1, 32LL, 32LL);
interpret_imm(a1, 16, 157);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 101);
interpret_ldm(a1, 1LL, 1LL);
interpret_cmp(a1, 1LL, 32LL);
if ( (a1[262] & 2) == 0 )
v2 = 0;
interpret_imm(a1, 32, 134);
interpret_ldm(a1, 32LL, 32LL);
interpret_imm(a1, 16, 216);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 102);
interpret_ldm(a1, 1LL, 1LL);
interpret_cmp(a1, 1LL, 32LL);
if ( (a1[262] & 2) == 0 )
v2 = 0;
interpret_imm(a1, 32, 135);
interpret_ldm(a1, 32LL, 32LL);
interpret_imm(a1, 16, 84);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 103);
interpret_ldm(a1, 1LL, 1LL);
interpret_cmp(a1, 1LL, 32LL);
if ( (a1[262] & 2) == 0 )
v2 = 0;
interpret_imm(a1, 32, 136);
interpret_ldm(a1, 32LL, 32LL);
interpret_imm(a1, 16, 51);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 104);
interpret_ldm(a1, 1LL, 1LL);
interpret_cmp(a1, 1LL, 32LL);
if ( (a1[262] & 2) == 0 )
v2 = 0;
interpret_imm(a1, 32, 137);
interpret_ldm(a1, 32LL, 32LL);
interpret_imm(a1, 16, 199);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 105);
interpret_ldm(a1, 1LL, 1LL);
interpret_cmp(a1, 1LL, 32LL);
if ( (a1[262] & 2) == 0 )
v2 = 0;
interpret_imm(a1, 32, 138);
interpret_ldm(a1, 32LL, 32LL);
interpret_imm(a1, 16, 8);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 106);
interpret_ldm(a1, 1LL, 1LL);
interpret_cmp(a1, 1LL, 32LL);
if ( (a1[262] & 2) == 0 )
v2 = 0;
interpret_imm(a1, 32, 139);
interpret_ldm(a1, 32LL, 32LL);
interpret_imm(a1, 16, 41);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 107);
interpret_ldm(a1, 1LL, 1LL);
interpret_cmp(a1, 1LL, 32LL);
if ( (a1[262] & 2) == 0 )
v2 = 0;
interpret_imm(a1, 1, 1);
interpret_imm(a1, 32, 0);
interpret_imm(a1, 16, 1);
if ( v2 )
{
interpret_imm(a1, 2, 67);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 79);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 82);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 82);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 69);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 67);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 84);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 33);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 32);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 89);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 111);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 117);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 114);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 32);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 102);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 108);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 97);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 103);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 58);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 10);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 47);
interpret_imm(a1, 32, 0);
interpret_stm(a1, 32LL, 2LL);
interpret_imm(a1, 2, 102);
interpret_imm(a1, 32, 1);
interpret_stm(a1, 32LL, 2LL);
interpret_imm(a1, 2, 108);
interpret_imm(a1, 32, 2);
interpret_stm(a1, 32LL, 2LL);
interpret_imm(a1, 2, 97);
interpret_imm(a1, 32, 3);
interpret_stm(a1, 32LL, 2LL);
interpret_imm(a1, 2, 103);
interpret_imm(a1, 32, 4);
interpret_stm(a1, 32LL, 2LL);
interpret_imm(a1, 2, 0);
interpret_imm(a1, 32, 5);
interpret_stm(a1, 32LL, 2LL);
interpret_imm(a1, 1, 0);
interpret_imm(a1, 32, 0);
interpret_sys(a1, 16LL, 1LL);
interpret_imm(a1, 16, 100);
interpret_sys(a1, 32LL, 16LL);
interpret_imm(a1, 1, 1);
interpret_sys(a1, 2LL, 16LL);
interpret_imm(a1, 1, 0);
}
else
{
interpret_imm(a1, 2, 73);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 78);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 67);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 79);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 82);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 82);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 69);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 67);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 84);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 2, 33);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
interpret_imm(a1, 1, 1);
}
interpret_imm(a1, 2, 10);
interpret_stm(a1, 32LL, 2LL);
interpret_sys(a1, 2LL, 1LL);
return interpret_sys(a1, 4LL, 1LL);
}
The first part
interpret_imm(a1, 32, 128);
interpret_ldm(a1, 32LL, 32LL);
interpret_imm(a1, 16, 17);
interpret_add(a1, 32LL, 16LL);
interpret_imm(a1, 1, 96);
interpret_ldm(a1, 1LL, 1LL);
interpret_cmp(a1, 1LL, 32LL);
It does
//a1[257] = 128
interpret_imm(a1, 32, 128)
//index = a1[257] (=128)
///a1[257] = a1[index]
interpret_ldm(a1, 32, 32)
//a1[258] = 17
interpret_imm(a1, 16, 17)
//a1[257] += a1[258]
interpret_add(a1, 32, 16)
//a1[256] = 96
interpret_imm(a1, 1, 96)
//index = a1[256]
//memory = a1[index]
//a1[256] = memory
// ~~~ a1[256] = a1[96]
interpret_ldm(a1, 1, 1)
//compare a1[256] and a1[257]
interpret_cmp(a1, 1, 32)
main
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
__int64 dest[128]; // [rsp+10h] [rbp-410h] BYREF
int v4; // [rsp+410h] [rbp-10h]
__int16 v5; // [rsp+414h] [rbp-Ch]
char v6; // [rsp+416h] [rbp-Ah]
unsigned __int64 v7; // [rsp+418h] [rbp-8h]
v7 = __readfsqword(0x28u);
printf("[+] Welcome to %s!\n", *argv);
puts("[+] This challenge is an custom emulator. It emulates a completely custom");
puts("[+] architecture that we call \"Yan85\"! You'll have to understand the");
puts("[+] emulator to understand the architecture, and you'll have to understand");
puts("[+] the architecture to understand the code being emulated, and you will");
puts("[+] have to understand that code to get the flag. Good luck!");
puts("[+]");
puts("[+] This level is a full Yan85 emulator. You'll have to reason about yancode,");
puts("[+] and the implications of how the emulator interprets it!");
setvbuf(stdout, 0LL, 2, 1uLL);
memset(dest, 0, sizeof(dest));
v4 = 0;
v5 = 0;
v6 = 0;
memcpy(dest, &vm_code, (unsigned int)vm_code_length);
dest[96] = vm_mem;
dest[97] = qword_5328;
dest[98] = qword_5330;
dest[99] = qword_5338;
dest[100] = qword_5340;
dest[101] = qword_5348;
dest[102] = qword_5350;
dest[103] = qword_5358;
dest[104] = qword_5360;
dest[105] = qword_5368;
dest[106] = qword_5370;
dest[107] = qword_5378;
dest[108] = qword_5380;
dest[109] = qword_5388;
dest[110] = qword_5390;
dest[111] = qword_5398;
dest[112] = qword_53A0;
dest[113] = qword_53A8;
dest[114] = qword_53B0;
dest[115] = qword_53B8;
dest[116] = qword_53C0;
dest[117] = qword_53C8;
dest[118] = qword_53D0;
dest[119] = qword_53D8;
dest[120] = qword_53E0;
dest[121] = qword_53E8;
dest[122] = qword_53F0;
dest[123] = qword_53F8;
dest[124] = qword_5400;
dest[125] = qword_5408;
dest[126] = qword_5410;
dest[127] = qword_5418;
interpreter_loop(dest);
}
It copies vm_code into dest after calling memset(make dest 0).
vm_mem has the unknown byte, so I check it in pwndbg
interpreter_loop
void __fastcall __noreturn interpreter_loop(__int64 a1)
{
unsigned __int8 v1; // al
puts("[+] Starting interpreter loop! Good luck!");
while ( 1 )
{
v1 = *(_BYTE *)(a1 + 1029);
*(_BYTE *)(a1 + 1029) = v1 + 1;
interpret_instruction(
a1,
*(unsigned __int16 *)(a1 + 3LL * v1) | ((unsigned __int64)*(unsigned __int8 *)(a1 + 3LL * v1 + 2) << 16));
}
}
interpret_instruction
__int64 __fastcall interpret_instruction(unsigned __int8 *a1, __int64 a2)
{
__int64 result; // rax
printf(
"[V] a:%#hhx b:%#hhx c:%#hhx d:%#hhx s:%#hhx i:%#hhx f:%#hhx\n",
a1[1024],
a1[1025],
a1[1026],
a1[1027],
a1[1028],
a1[1029],
a1[1030]);
printf("[I] op:%#hhx arg1:%#hhx arg2:%#hhx\n", (unsigned __int8)a2, BYTE2(a2), BYTE1(a2));
if ( (a2 & 0x40) != 0 )
interpret_imm(a1, a2);
if ( (a2 & 0x10) != 0 )
interpret_add(a1, a2);
if ( (a2 & 0x80u) != 0LL )
interpret_stk(a1, a2);
if ( (a2 & 1) != 0 )
interpret_stm(a1, a2);
if ( (a2 & 8) != 0 )
interpret_ldm(a1, a2);
if ( (a2 & 0x20) != 0 )
interpret_cmp(a1, a2);
if ( (a2 & 2) != 0 )
interpret_jmp(a1, a2);
result = a2 & 4;
if ( (a2 & 4) != 0 )
return interpret_sys(a1, a2);
return result;
}
It takes the byte instruction to call the respective function.
The big difference in this level is that the program doesn't give the code.
I spent many times thinking about the approach to solving this level and writing a script for it.
[+] v1 @ 0xb6
[+] x | y @ 0x204004
[V] a:0x0 b:0x30 c:0xe d:0x1 s:0x8 i:0xb7 f:0x0
[I] op:0x4 arg1:0x20 arg2:0x40
[*] SYS
[s] SYS 0x20 d
[s] ... read_memory
input: aa
[s] ... return value (in register d): 0x2
a1[1024] = 0x0 a1[1025] = 0x30 a1[1026] = 0xe a1[1027] = 0x2 a1[1028] = 0x8 a1[1029] = 0xb7 a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x204004
index = a1[1025] = 0x30
a1[index + 768] = a1[816] = input
Sent byte: aaaa
[+] v1 @ 0x6
[+] x | y @ 0x40ff40
[V] a:0x3c b:0x79 c:0xc d:0x95 s:0x6 i:0x7 f:0x0
[I] op:0x40 arg1:0x40 arg2:0xff
[*] IMM
IMM d = 0xff
a1[1024] = 0x3c a1[1025] = 0x79 a1[1026] = 0xc a1[1027] = 0xff a1[1028] = 0x6 a1[1029] = 0x7 a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x40ff40
=> a1[1027] = 0xff
[+] v1 @ 0x7
[+] x | y @ 0x24010
[V] a:0x3c b:0x79 c:0xc d:0xff s:0x6 i:0x8 f:0x0
[I] op:0x10 arg1:0x2 arg2:0x40
[*] ADD
[s] ADD a d
a1[1024] = 0x3b a1[1025] = 0x79 a1[1026] = 0xc a1[1027] = 0xff a1[1028] = 0x6 a1[1029] = 0x8 a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x24010
v2 = a1[1024] = 0x3c
v4 = a1[1027] = 0xff
a1[1024] = v2 + v4 = 0x3b
=> a1[1024] += a1[1027]
[+] v1 @ 0x8
[+] x | y @ 0x14010
[V] a:0x3b b:0x79 c:0xc d:0xff s:0x6 i:0x9 f:0x0
[I] op:0x10 arg1:0x1 arg2:0x40
[*] ADD
[s] ADD b d
a1[1024] = 0x3b a1[1025] = 0x78 a1[1026] = 0xc a1[1027] = 0xff a1[1028] = 0x6 a1[1029] = 0x9 a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x14010
v2 = a1[1025] = 0x78
v4 = a1[1027] = 0xff
a1[1024] = v2 + v4 = 0x78
=> a1[1025] += a1[1027]
[+] v1 @ 0x9
[+] x | y @ 0x280
[V] a:0x3b b:0x78 c:0xc d:0xff s:0x6 i:0xa f:0x0
[I] op:0x80 arg1:0x0 arg2:0x2
[*] STK
[s] STK N a
[s] ... pushing a
a1[1024] = 0x3b a1[1025] = 0x78 a1[1026] = 0xc a1[1027] = 0xff a1[1028] = 0x7 a1[1029] = 0xa a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x000280
a1[2018]++
v5 = a1[1024] = 0x3b
index = a1[2018] = 0x7
a1[index + 768] = v5
=> a1[775] = a1[1024] = 0x3b
[+] v1 @ 0xa
[+] x | y @ 0x180
[V] a:0x3b b:0x78 c:0xc d:0xff s:0x7 i:0xb f:0x0
[I] op:0x80 arg1:0x0 arg2:0x1
[*] STK
[s] STK N b
[s] ... pushing b
a1[1024] = 0x3b a1[1025] = 0x78 a1[1026] = 0xc a1[1027] = 0xff a1[1028] = 0x8 a1[1029] = 0xb a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x000180
a1[2018]++
v5 = a1[1025] = 0x78
index = a1[2018] = 0x8
a1[index + 768] = v5
=> a1[776] = a1[1025] = 0x78
[+] v1 @ 0xb
[+] x | y @ 0x20208
[V] a:0x3b b:0x78 c:0xc d:0xff s:0x8 i:0xc f:0x0
[I] op:0x8 arg1:0x2 arg2:0x2
[*] LDM
[s] LDM a = *a
[*] v4 @ 0x3b
[*] memory @ 0x0
a1[1024] = 0x0 a1[1025] = 0x78 a1[1026] = 0xc a1[1027] = 0xff a1[1028] = 0x8 a1[1029] = 0xc a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x020208
v4 = a1[1024] = 0x3b
memory = a1[v4 + 768] = a1[827] = 0x0
a1[1024] = memory
=> a1[1024] = a1[827]
[+] v1 @ 0xc
[+] x | y @ 0x10108
[V] a:0x0 b:0x78 c:0xc d:0xff s:0x8 i:0xd f:0x0
[I] op:0x8 arg1:0x1 arg2:0x1
[*] LDM
[s] LDM b = *b
[*] v4 @ 0x78
[*] memory @ 0x45
a1[1024] = 0x0 a1[1025] = 0x45 a1[1026] = 0xc a1[1027] = 0xff a1[1028] = 0x8 a1[1029] = 0xd a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x010108
v4 = a1[1025] = 0x78
memory = a1[v4 + 768] = a1[888] = 0x45
a1[1025] = memory
=> a1[1025] = a1[888]
[+] v1 @ 0xd
[+] x | y @ 0x20120
[V] a:0x0 b:0x45 c:0xc d:0xff s:0x8 i:0xe f:0x0
[I] op:0x20 arg1:0x2 arg2:0x1
[*] CMP
[s] CMP a = b
a1[1024] = 0x0 a1[1025] = 0x45 a1[1026] = 0xc a1[1027] = 0xff a1[1028] = 0x8 a1[1029] = 0xe a1[1030] = 0x12 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x020120
compare a1[1024] and a1[1025]
=> compare a1[827]( ~ input[12]) and a1[888] = 0x45
[+] v1 @ 0xe
[+] x | y @ 0x10080
[V] a:0x0 b:0x45 c:0xc d:0xff s:0x8 i:0xf f:0x12
[I] op:0x80 arg1:0x1 arg2:0x0
[*] STK
[s] STK b N
[s] ... popping b
a1[1024] = 0x0 a1[1025] = 0x78 a1[1026] = 0xc a1[1027] = 0xff a1[1028] = 0x7 a1[1029] = 0xf a1[1030] = 0x12 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x10080
index = a1[1028] = 0x8
memory = a1[index + 768] = a1[776] = 0x78
a1[1025] = memory = 0x78
a1[1028]--
=> a1[1025] = a1[776]
[+] v1 @ 0xf
[+] x | y @ 0x20080
[V] a:0x0 b:0x78 c:0xc d:0xff s:0x7 i:0x10 f:0x12
[I] op:0x80 arg1:0x2 arg2:0x0
[*] STK
[s] STK a N
[s] ... popping a
a1[1024] = 0x3b a1[1025] = 0x78 a1[1026] = 0xc a1[1027] = 0xff a1[1028] = 0x6 a1[1029] = 0x10 a1[1030] = 0x12 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x20080
index = a1[1028] = 0x7
memory = a1[index + 768] = a1[775] = 0x3b
a1[1024] = memory = 0x3b
a1[1028]--
=> a1[1024] = a1[775]
[+] v1 @ 0x10
[+] x | y @ 0x401840
[V] a:0x3b b:0x78 c:0xc d:0xff s:0x6 i:0x11 f:0x12
[I] op:0x40 arg1:0x40 arg2:0x18
[*] IMM
IMM d = 0x18
a1[1024] = 0x3b a1[1025] = 0x78 a1[1026] = 0xc a1[1027] = 0x18 a1[1028] = 0x6 a1[1029] = 0x11 a1[1030] = 0x12 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x401840
=> a1[1027] = 0x18
[+] v1 @ 0x11
[+] x | y @ 0x104002
[V] a:0x3b b:0x78 c:0xc d:0x18 s:0x6 i:0x12 f:0x12
[I] op:0x2 arg1:0x10 arg2:0x40
[*] JMP
[j] JMP N\x00 d
[j] ... TAKEN
a1[1024] = 0x3b a1[1025] = 0x78 a1[1026] = 0xc a1[1027] = 0x18 a1[1028] = 0x6 a1[1029] = 0x18 a1[1030] = 0x12 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x104002
result = a1[1027] = 0x18
a1[1029] = result
=> a1[1029] = a1[1027]
[+] v1 @ 0x18
[+] x | y @ 0x401080
[V] a:0x3b b:0x78 c:0xc d:0x18 s:0x6 i:0x19 f:0x12
[I] op:0x80 arg1:0x40 arg2:0x10
[*] STK
[s] STK d c
[s] ... pushing c
[s] ... popping d
a1[1024] = 0x3b a1[1025] = 0x78 a1[1026] = 0xc a1[1027] = 0xc a1[1028] = 0x6 a1[1029] = 0x19 a1[1030] = 0x12 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x401080
pushing:
a1[1028]++
v5 = a1[1026] = 0xc
index = a1[1028] = 0x7
a1[index + 768] = a1[775] = v5
=> a1[775] = a1[1026]
popping
index = a1[1028] = 0x7
memory = a1[index + 768] = a1[775]
a1[1027] = memory
a1[1028]--
=> a1[1027] = a1[775]
=> a1[1027] = a1[1026]
[+] v1 @ 0x19
[+] x | y @ 0x200080
[V] a:0x3b b:0x78 c:0xc d:0xc s:0x6 i:0x1a f:0x12
[I] op:0x80 arg1:0x20 arg2:0x0
[*] STK
[s] STK i N
[s] ... popping i
a1[1024] = 0x3b a1[1025] = 0x78 a1[1026] = 0xc a1[1027] = 0xc a1[1028] = 0x5 a1[1029] = 0x95 a1[1030] = 0x12 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x200080
index = a1[1028]
memory = a1[index + 768] = a1[774] = 0x95
a1[1029] = memory
=> a1[1029] = a1[774] = 0x95
[+] v1 @ 0x95
[+] x | y @ 0x100040
[V] a:0x3b b:0x78 c:0xc d:0xc s:0x5 i:0x96 f:0x12
[I] op:0x40 arg1:0x10 arg2:0x0
[*] IMM
IMM c = 0x0
a1[1024] = 0x3b a1[1025] = 0x78 a1[1026] = 0x0 a1[1027] = 0xc a1[1028] = 0x5 a1[1029] = 0x96 a1[1030] = 0x12 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x100040
=> a1[1026] = 0x0
[+] v1 @ 0x96
[+] x | y @ 0x401020
[V] a:0x3b b:0x78 c:0x0 d:0xc s:0x5 i:0x97 f:0x12
[I] op:0x20 arg1:0x40 arg2:0x10
[*] CMP
[s] CMP d = c
a1[1024] = 0x3b a1[1025] = 0x78 a1[1026] = 0x0 a1[1027] = 0xc a1[1028] = 0x5 a1[1029] = 0x97 a1[1030] = 0x14 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x401020
=>compare a1[1026] and a1[1027]
However, this program make a1[1026] = 0x0
and a1[1027]
is equal to the old value of a1[1026]
(force a1[1026] = 0xc
~ IMM c = 0xc
)
I don't think what does this compare mean? Thus, I try to pass the first compare and see the result
Sent byte: aaaaaaaaaaaE
[+] v1 @ 0x16
[+] x | y @ 0x400640
[V] a:0x3b b:0x78 c:0xb d:0x0 s:0x6 i:0x17 f:0x14
[I] op:0x40 arg1:0x40 arg2:0x6
[*] IMM
IMM d = 0x6
a1[1024] = 0x3b a1[1025] = 0x78 a1[1026] = 0xb a1[1027] = 0x6 a1[1028] = 0x6 a1[1029] = 0x17 a1[1030] = 0x14 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x400640
=> a1[1027] = 0x6
[+] v1 @ 0x17
[+] x | y @ 0x104002
[V] a:0x3b b:0x78 c:0xb d:0x6 s:0x6 i:0x18 f:0x14
[I] op:0x2 arg1:0x10 arg2:0x40
[*] JMP
[j] JMP N\x00 d
[j] ... TAKEN
a1[1024] = 0x3b a1[1025] = 0x78 a1[1026] = 0xb a1[1027] = 0x6 a1[1028] = 0x6 a1[1029] = 0x6 a1[1030] = 0x14 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
result = a1[1027] = 0x6
a1[1029] = a1[1027]
=> a1[1029] = a1[1027]
[+] v1 @ 0x6
[+] x | y @ 0x40ff40
[V] a:0x3b b:0x78 c:0xb d:0x6 s:0x6 i:0x7 f:0x14
[I] op:0x40 arg1:0x40 arg2:0xff
[*] IMM
IMM d = 0xff
a1[1024] = 0x3b a1[1025] = 0x78 a1[1026] = 0xb a1[1027] = 0xff a1[1028] = 0x6 a1[1029] = 0x7 a1[1030] = 0x14 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x40ff40
=> a1[1027] = 0xff
[+] v1 @ 0x7
[+] x | y @ 0x24010
[V] a:0x3b b:0x78 c:0xb d:0xff s:0x6 i:0x8 f:0x14
[I] op:0x10 arg1:0x2 arg2:0x40
[*] ADD
[s] ADD a d
a1[1024] = 0x3a a1[1025] = 0x78 a1[1026] = 0xb a1[1027] = 0xff a1[1028] = 0x6 a1[1029] = 0x8 a1[1030] = 0x14 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x24010
v2 = a1[1024] = 0x3a
v4 = a1[1027] = 0xff
a1[1024] = v2 + v4
=> a1[1024] += a1[1027]
[+] v1 @ 0x8
[+] x | y @ 0x14010
[V] a:0x3a b:0x78 c:0xb d:0xff s:0x6 i:0x9 f:0x14
[I] op:0x10 arg1:0x1 arg2:0x40
[*] ADD
[s] ADD b d
a1[1024] = 0x3a a1[1025] = 0x77 a1[1026] = 0xb a1[1027] = 0xff a1[1028] = 0x6 a1[1029] = 0x9 a1[1030] = 0x14 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x14010
v2 = a1[1025] = 0x3a
v4 = a1[1027] = 0xff
a1[1025] = v2 + v4
=> a1[1025] += a1[1027]
[+] v1 @ 0x9
[+] x | y @ 0x280
[V] a:0x3a b:0x77 c:0xb d:0xff s:0x6 i:0xa f:0x14
[I] op:0x80 arg1:0x0 arg2:0x2
[*] STK
[s] STK N a
[s] ... pushing a
a1[1024] = 0x3a a1[1025] = 0x77 a1[1026] = 0xb a1[1027] = 0xff a1[1028] = 0x7 a1[1029] = 0xa a1[1030] = 0x14 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x000280
a1[1028]++
v5 = a1[1024] = 0x3a
index = a1[1028]
a1[index + 768] = a1[775] = v5
=> a1[775] = a1[1024]
[+] v1 @ 0xa
[+] x | y @ 0x180
[V] a:0x3a b:0x77 c:0xb d:0xff s:0x7 i:0xb f:0x14
[I] op:0x80 arg1:0x0 arg2:0x1
[*] STK
[s] STK N b
[s] ... pushing b
a1[1024] = 0x3a a1[1025] = 0x77 a1[1026] = 0xb a1[1027] = 0xff a1[1028] = 0x8 a1[1029] = 0xb a1[1030] = 0x14 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x000180
a1[1028]++
v5 = a1[1025] = 0x77
index = a1[1028]
a1[index + 768] = a1[776] = v5
=> a1[776] = a1[1024]
[+] v1 @ 0xb
[+] x | y @ 0x20208
[V] a:0x3a b:0x77 c:0xb d:0xff s:0x8 i:0xc f:0x14
[I] op:0x8 arg1:0x2 arg2:0x2
[*] LDM
[s] LDM a = *a
[*] v4 @ 0x3a
[*] memory @ 0x61
a1[1024] = 0x61 a1[1025] = 0x77 a1[1026] = 0xb a1[1027] = 0xff a1[1028] = 0x8 a1[1029] = 0xc a1[1030] = 0x14 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x20208
v4 = a1[1024] = 0x3a
memory = a1[v4 + 768]= a1[826]
a1[1024] = memory
=> a1[1024] = a1[826]
[+] v1 @ 0xc
[+] x | y @ 0x10108
[V] a:0x61 b:0x77 c:0xb d:0xff s:0x8 i:0xd f:0x14
[I] op:0x8 arg1:0x1 arg2:0x1
[*] LDM
[s] LDM b = *b
[*] v4 @ 0x77
[*] memory @ 0xbb
a1[1024] = 0x61 a1[1025] = 0xbb a1[1026] = 0xb a1[1027] = 0xff a1[1028] = 0x8 a1[1029] = 0xd a1[1030] = 0x14 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
0x10108
v4 = a1[1025] = 0x77
memory = a1[v4 + 768] = a1[887]
=> a1[1025] = a1[888]
[+] v1 @ 0xd
[+] x | y @ 0x20120
[V] a:0x61 b:0xbb c:0xb d:0xff s:0x8 i:0xe f:0x14
[I] op:0x20 arg1:0x2 arg2:0x1
[*] CMP
[s] CMP a = b
a1[1024] = 0x61 a1[1025] = 0xbb a1[1026] = 0xb a1[1027] = 0xff a1[1028] = 0x8 a1[1029] = 0xe a1[1030] = 0x12 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
compare a1[1024] and a1[1025]
<=> compare a1[826] and a1[887]
Here, I will conclude my supposition and guess the work of compare.
First, it will compare the index 12 of my input(a1[827]) with the respective byte(a1[888])
Next, it compares something couple of value(I don't know what does this mean? I guess it will make the instruction for the next compare)
Then, it compares the similar couple, but index subtract 1 (a1[826] and a1[887])
And, the next unknown compare happens
This loop is has the rule, I follow with this and have the license key.
In this level, vm_mem is not empty.
[+] v1 @ 0xdc
[+] x | y @ 0x18004
[V] a:0x0 b:0x30 c:0x22 d:0x5 s:0x3 i:0xdd f:0x0
[I] op:0x80 arg1:0x4 arg2:0x1
[*] SYS
[s] SYS 0x4 d
[s] ... read_memory
input: aaaaaaaaaaaaaaaaaaaaaaaaaaaa
[s] ... return value (in register d): 0x1c
a1[1024] = 0x0 a1[1025] = 0x30 a1[1026] = 0x22 a1[1027] = 0x1c a1[1028] = 0x3 a1[1029] = 0xdd a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
input at index a1[768 + 0x30] ~ a1[816]
[+] v1 @ 0x3
[+] x | y @ 0xff0801
[V] a:0x4c b:0xb8 c:0x1c d:0xc6 s:0x1 i:0x4 f:0x0
[I] op:0x8 arg1:0x1 arg2:0xff
[*] IMM
IMM d = 0xff
a1[1024] = 0x4c a1[1025] = 0xb8 a1[1026] = 0x1c a1[1027] = 0xff a1[1028] = 0x1 a1[1029] = 0x4 a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
=> a1[1027] = 0xff
[+] v1 @ 0x4
[+] x | y @ 0x14010
[V] a:0x4c b:0xb8 c:0x1c d:0xff s:0x1 i:0x5 f:0x0
[I] op:0x40 arg1:0x10 arg2:0x1
[*] ADD
[s] ADD a d
a1[1024] = 0x4b a1[1025] = 0xb8 a1[1026] = 0x1c a1[1027] = 0xff a1[1028] = 0x1 a1[1029] = 0x5 a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
v2 = a1[1024] = 0x4b
v4 = a1[1027] = 0xff
a1[1024] = v2 + v4
=> a1[1024] += a1[1027]
[+] v1 @ 0x5
[+] x | y @ 0x14002
[V] a:0x4b b:0xb8 c:0x1c d:0xff s:0x1 i:0x6 f:0x0
[I] op:0x40 arg1:0x2 arg2:0x1
[*] ADD
[s] ADD b d
a1[1024] = 0x4b a1[1025] = 0xb7 a1[1026] = 0x1c a1[1027] = 0xff a1[1028] = 0x1 a1[1029] = 0x6 a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
v2 = a1[1025] = 0xb7
v4 = a1[1027] = 0xff
a1[1025] = v2 + v4
=> a1[1025] += a1[1027]
[+] v1 @ 0x6
[+] x | y @ 0x100200
[V] a:0x4b b:0xb7 c:0x1c d:0xff s:0x1 i:0x7 f:0x0
[I] op:0x2 arg1:0x0 arg2:0x10
[*] STK
[s] STK N a
[s] ... pushing a
a1[1024] = 0x4b a1[1025] = 0xb7 a1[1026] = 0x1c a1[1027] = 0xff a1[1028] = 0x2 a1[1029] = 0x7 a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
a1[1028]++
v5 = a1[1024] = 0x4b
index = a1[1028]
a1[index + 768] = v5
=> a1[770] = 0x4b
[+] v1 @ 0x7
[+] x | y @ 0x20200
[V] a:0x4b b:0xb7 c:0x1c d:0xff s:0x2 i:0x8 f:0x0
[I] op:0x2 arg1:0x0 arg2:0x2
[*] STK
[s] STK N b
[s] ... pushing b
a1[1024] = 0x4b a1[1025] = 0xb7 a1[1026] = 0x1c a1[1027] = 0xff a1[1028] = 0x3 a1[1029] = 0x8 a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
a1[1028]++
v5 = a1[1025] = 0xb7
index = a1[1028]
a1[index + 768] = v5
=> a1[771] = 0x4b
[+] v1 @ 0x8
[+] x | y @ 0x102010
[V] a:0x4b b:0xb7 c:0x1c d:0xff s:0x3 i:0x9 f:0x0
[I] op:0x20 arg1:0x10 arg2:0x10
[*] LDM
[s] LDM a = *a
[*] v4 @ 0x4b
[*] memory @ 0x7
a1[1024] = 0x7 a1[1025] = 0xb7 a1[1026] = 0x1c a1[1027] = 0xff a1[1028] = 0x3 a1[1029] = 0x9 a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
v4 = a1[1024] = 0x4b
memory = a1[768 +v4] = a1[843]
a1[1024] = memory
=> a1[1024] = a1[843]
[+] v1 @ 0x9
[+] x | y @ 0x22002
[V] a:0x7 b:0xb7 c:0x1c d:0xff s:0x3 i:0xa f:0x0
[I] op:0x20 arg1:0x2 arg2:0x2
[*] LDM
[s] LDM b = *b
[*] v4 @ 0xb7
[*] memory @ 0x62
a1[1024] = 0x7 a1[1025] = 0x62 a1[1026] = 0x1c a1[1027] = 0xff a1[1028] = 0x3 a1[1029] = 0xa a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
v4 = a1[1025] = 0xb7
memory = a1[768 +v4] = a1[951]
a1[1024] = memory
=> a1[1025] = a1[951]
[+] v1 @ 0xa
[+] x | y @ 0x20410
[V] a:0x7 b:0x62 c:0x1c d:0xff s:0x3 i:0xb f:0x0
[I] op:0x4 arg1:0x10 arg2:0x2
[*] CMP
[s] CMP a = b
a1[1024] = 0x7 a1[1025] = 0x62 a1[1026] = 0x1c a1[1027] = 0xff a1[1028] = 0x3 a1[1029] = 0xb a1[1030] = 0x3 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
compare a1[1024] and a1[1025]
<=> compare a1[843] and a1[951]
In this level, I can use the same trick to solve this challenge as in the previous level. However, in the previous challenge, I knew that my input remains unchanged and is compared with the license key, so to solve the problem quickly, I write some code to find each key ╰(°▽°)╯. Now, I can also calculate the distance between my input and the value of my input after changing it and the license key I get; and I can solve this successfully, but I don't do this; I'm legit (●'◡'●).
I get one of the changes my input, and the others are the same.
[+] v1 @ 0xa1
[+] x | y @ 0x4b0810
[V] a:0x4a b:0x36 c:0xd5 d:0x1c s:0x3 i:0xa2 f:0x0
[I] op:0x8 arg1:0x10 arg2:0x4b
[*] IMM
IMM a = 0x4b
a1[1024] = 0x4b a1[1025] = 0x36 a1[1026] = 0xd5 a1[1027] = 0x1c a1[1028] = 0x3 a1[1029] = 0xa2 a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
=> a1[1024] = 0x4b
[+] v1 @ 0xa2
[+] x | y @ 0xa60840
[V] a:0x4b b:0x36 c:0xd5 d:0x1c s:0x3 i:0xa3 f:0x0
[I] op:0x8 arg1:0x40 arg2:0xa6
[*] IMM
IMM c = 0xa6
a1[1024] = 0x4b a1[1025] = 0x36 a1[1026] = 0xa6 a1[1027] = 0x1c a1[1028] = 0x3 a1[1029] = 0xa3 a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
=> a1[1026] = 0xa6
[+] v1 @ 0xa3
[+] x | y @ 0x102002
[V] a:0x4b b:0x36 c:0xa6 d:0x1c s:0x3 i:0xa4 f:0x0
[I] op:0x20 arg1:0x2 arg2:0x10
[*] LDM
[s] LDM b = *a
[*] v4 @ 0x4b
[*] memory @ 0x61
a1[1024] = 0x4b a1[1025] = 0x61 a1[1026] = 0xa6 a1[1027] = 0x1c a1[1028] = 0x3 a1[1029] = 0xa4 a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
v4 = a1[1024] = 0x4b
memory = a1[768 + v4] = a1[843]
a1[1025] = memory
=> a1[1025] = a1[843]
[+] v1 @ 0xa4
[+] x | y @ 0x404002
[V] a:0x4b b:0x61 c:0xa6 d:0x1c s:0x3 i:0xa5 f:0x0
[I] op:0x40 arg1:0x2 arg2:0x40
[*] ADD
[s] ADD b c
a1[1024] = 0x4b a1[1025] = 0x7 a1[1026] = 0xa6 a1[1027] = 0x1c a1[1028] = 0x3 a1[1029] = 0xa5 a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
v2 = a1[1025] = 0x61
v4 = a1[1026] = 0xa6
a1[1025] = v2 + v4
=> a1[1025] = a1[1025] + a1[1026]
[+] v1 @ 0xa5
[+] x | y @ 0x21010
[V] a:0x4b b:0x7 c:0xa6 d:0x1c s:0x3 i:0xa6 f:0x0
[I] op:0x10 arg1:0x10 arg2:0x2
[*] STM
[s] STM *a = b
a1[1024] = 0x4b a1[1025] = 0x7 a1[1026] = 0xa6 a1[1027] = 0x1c a1[1028] = 0x3 a1[1029] = 0xa6 a1[1030] = 0x0 a1[1031] = 0x0 a1[1032] = 0x0 a1[1033] = 0x0
v2 = a1[1025] = 0x7
v4 = a1[1024] = 0x4b
index = v4 = 0x4b
a1[index + 768] = v2
=> a1[843] = a1[1025]
IMM a = 0x4b (get index)→ IMM c = 0xa6 (get value to add ~ distance) → [s] LDM b = *a (init value at index 0x4b) → [s] ADD b c (add distance) → [s] STM *a = b (store value after changes to old index)
value_add = [0x48, 0x9c, 0xa , 0x9a , 0x3f , 0x41 ,0x93, 0x94 ,0xac , 0xd4,0x72 ,0xdd ,0x5a ,0x7, 0xc6, 0x90,0xa2,0xc0 ,0xdd,0x37, 0xa4,0x4,0x22, 0x9c, 0xad, 0xc2, 0xd5, 0xa6]
A hypervisor is a software that you can use to run multiple virtual machines on a single physical machine. Every virtual machine has its own operating system and applications. The hypervisor allocates the underlying physical computing resources such as CPU and memory to individual virtual machines as required.
Aug 2, 2024:::
Jul 11, 2024:::
Jul 4, 2024checks
Jun 28, 2024or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up