[Wangding Cup 2020 Blue Dragon Group] singal
step
- Routine inspection, 32-bit program, no shell
- Try the program locally
- 32-bit ida is loaded. First, find the main function and determine the style of the flag string. Flag{……}
According to the prompt string of the input point, find the corresponding function, and confirm that the length of the string is 15
right-click the function and find the call The place of this function comes to the vm_operad() function. Look at the main function to know that the parameter v4 in vm_operad calls the qmemcpy function in the upper line. Baidu says that qmemcpy=memcpy in the reverse direction is the copy function of memcpy in the C language. , Copy 0x1C8 bytes of data in unk_403040 to v4
unk_403040 This address has a lot of data copy 0x1C8 is
selected to 0x403208 , shift+e is converted into an array of
4 bytes equal to an int, the interl processor is little-endian storage, just right The value of the a1 array is the hexadecimal number before the three 00s. To sort it out,
v4=[10, 4, 16, 8, 3, 5, 1, 4, 32, 8, 5, 3, 1, 3, 2, 8, 11, 1, 12, 8, 4, 4, 1, 5, 3, 8, 3, 33, 1, 11, 8, 11, 1, 4, 9, 8, 3, 32, 1, 2, 81, 8, 4, 36, 1, 12, 8, 11, 1, 5, 2, 8, 2, 37, 1, 2, 54, 8, 4, 65, 1, 2, 32, 8, 5, 1, 1, 5, 3, 8, 2, 37, 1, 4, 9, 8, 3, 32, 1, 2, 65, 8, 12, 1]
pay attention to the little-endian order when the 32-bit program is stored. I will not reverse the order. Let’s look for the processing in the memory. Some data at the time
Then call the array and 114 enter the vm_operad function
int __cdecl vm_operad(int *a1, int _114)
{
int result; // eax
char Str[200]; // [esp+13h] [ebp-E5h] BYREF
char v4; // [esp+DBh] [ebp-1Dh]
int v5; // [esp+DCh] [ebp-1Ch]
int v6; // [esp+E0h] [ebp-18h]
int v7; // [esp+E4h] [ebp-14h]
int v8; // [esp+E8h] [ebp-10h]
int v9; // [esp+ECh] [ebp-Ch]
v9 = 0;
v8 = 0;
v7 = 0;
v6 = 0;
v5 = 0;
while ( 1 )
{
result = v9;
if ( v9 >= _114 )
return result;
switch ( a1[v9] )
{
case 1:
Str[v6 + 100] = v4;
++v9;
++v6;
++v8;
break;
case 2:
v4 = a1[v9 + 1] + Str[v8];
v9 += 2;
break;
case 3:
v4 = Str[v8] - LOBYTE(a1[v9 + 1]);
v9 += 2;
break;
case 4:
v4 = a1[v9 + 1] ^ Str[v8];
v9 += 2;
break;
case 5:
v4 = a1[v9 + 1] * Str[v8];
v9 += 2;
break;
case 6:
++v9;
break;
case 7:
if ( Str[v7 + 100] != a1[v9 + 1] )
{
printf("what a shame...");
exit(0);
}
++v7;
v9 += 2;
break;
case 8:
Str[v5] = v4;
++v9;
++v5;
break;
case 10:
read(Str);
++v9;
break;
case 11:
v4 = Str[v8] - 1;
++v9;
break;
case 12:
v4 = Str[v8] + 1;
++v9;
break;
default:
continue;
}
}
}
When the value is equal to 7, the value of the str array will be compared with the next bit of the a1 array, and the equality will continue without waiting for an error. The number after 7 is the value that needs to be compared with the correct input after encryption, just the value of 7 is at the end of the a1 array, extract this string of values
str=[]
a1=[10, 4, 16, 8, 3, 5, 1, 4, 32, 8, 5, 3, 1, 3, 2, 8, 11, 1, 12, 8, 4, 4, 1, 5, 3, 8, 3, 33, 1, 11, 8, 11, 1, 4, 9, 8, 3, 32, 1, 2, 81, 8, 4, 36, 1, 12, 8, 11, 1, 5, 2, 8, 2, 37, 1, 2, 54, 8, 4, 65, 1, 2, 32, 8, 5, 1, 1, 5, 3, 8, 2, 37, 1, 4, 9, 8, 3, 32, 1, 2, 65, 8, 12, 1, 7, 34, 7, 63, 7, 52, 7, 50, 7, 114, 7, 51, 7, 24, 7, 167, 255, 255, 255, 7, 49, 7, 241, 255, 255, 255, 7, 40, 7, 132, 255, 255, 255, 7, 193, 255, 255, 255, 7, 30, 7, 122]
for i in range(0,len(a1)):
if a1[i]==7:
str.append(a1[i+1])
print(a1)
str=[34, 63, 52, 50, 114, 51, 24, 167, 49, 241, 40, 132, 193, 30, 122]
Then the other case options in switch are operations on the str array, and finally get The value in str, the reverse algorithm to solve
There is a function called LOBYTE in it. When I did it, I went to Baidu. Some said it was the rightmost one, and some said the four digits on the right. There is no unified statement. I found the wp of other masters and said that this is a function of ida. Ignore this function. rax is a 64-bit register, eax is a 32-bit register, ax is a 16-bit register, al is the lower 8 bits of the ax register, and ah is the upper 8 bits of the ax register.
a1=[]
v4=[10, 4, 16, 8, 3, 5, 1, 4, 32, 8, 5, 3, 1, 3, 2, 8, 11, 1, 12, 8, 4, 4, 1, 5, 3, 8, 3, 33, 1, 11, 8, 11, 1, 4, 9, 8, 3, 32, 1, 2, 81, 8, 4, 36, 1, 12, 8, 11, 1, 5, 2, 8, 2, 37, 1, 2, 54, 8, 4, 65, 1, 2, 32, 8, 5, 1, 1, 5, 3, 8, 2, 37, 1, 4, 9, 8, 3, 32, 1, 2, 65, 8, 12, 1, 7, 34, 7, 63, 7, 52, 7, 50, 7, 114, 7, 51, 7, 24, 7, 167, 255, 255, 255, 7, 49, 7, 241, 255, 255, 255, 7, 40, 7, 132, 255, 255, 255, 7, 193, 255, 255, 255, 7, 30, 7, 122]
for i in range(0,len(v4)):
if v4[i]==7:
a1.append(v4[i+1])
#print(a1)
a1 = [34, 63, 52, 50, 114, 51, 24, 167, 49, 241, 40, 132, 193, 30, 122]
a1.reverse()
v4.reverse()
v9 = 0
us = 0
v5 = 0
flag = []
for i in range(0, len(v4)):
if i == len(v4) - 1:
flag.append(us)
if v4[i] == 1 and v4[i - 1] != 1:
v5 = a1[v9]
v9 += 1
flag.append(us)
if v4[i] == 2:
if (v4[i + 1] != 3 and v4[i + 1] != 4 and v4[i + 1] != 5):
us = v5 - v4[i - 1]
# print(us,v5,a[i-1])
if v4[i] == 3:
if (v4[i + 1] != 2 and v4[i + 1] != 4 and v4[i + 1] != 5):
us = v5 + v4[i - 1] # LOBYTE是al有8位,参与运算的5、33、32是全值,所以LOBYTE可省略
if v4[i] == 4:
if (v4[i + 1] != 3 and v4[i + 1] != 2 and v4[i + 1] != 5):
us = v5 ^ v4[i - 1]
if v4[i] == 5:
if (v4[i + 1] != 3 and v4[i + 1] != 4 and v4[i + 1] != 2):
us = int(v5 / v4[i - 1])
if v4[i] == 8:
v5 = us
if v4[i] == 11:
us = v5 + 1
if v4[i] == 12:
us = v5 - 1
# print("12:",us)
flag.reverse()
out = ''
for j in flag:
out += chr(j)
print("flag{" + out + "}")
flag{757515121f3d478 }