difficulty: 🩸 rank: 70 writeup: rev(1)
TM ( 🩸 247 pt, 45 solve )
TL;DR : simple function poiner vm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
int ReturnValue; // [rsp+4h] [rbp-1Ch]
int i; // [rsp+8h] [rbp-18h]
__int32 *Heap; // [rsp+10h] [rbp-10h]
__int32 *NextFunc; // [rsp+18h] [rbp-8h]
setup();
ptr = malloc(0x100uLL);
ptrPointer = ptr;
memset(ptr, 0, 0x100uLL);
buf = malloc(0x100uLL);
bufPointer = buf;
*(bufPointer + read(0, buf, 0x100uLL)) = 0;
Heap = *HeapArray;
ReturnValue = 1;
while ( ReturnValue )
{
NextFunc = HeapArray[Heap[*ptrPointer + 0x200]];
ReturnValue = (*&Heap[2 * *ptrPointer])();
Heap = NextFunc;
}
for ( i = 0; i <= 99; ++i )
free(HeapArray[i]);
free(ptr);
free(buf);
free(HeapArray);
return 0LL;
}
Just dropping the tm file to ida, see the pseudo-code
setup()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
HeapArray = (__int64 *)malloc((size_t)&MEMORY[0x4B000]);
memset(HeapArray, 0, (size_t)&MEMORY[0x4B000]);
v56 = malloc(0xC00uLL);
for ( i = 0; i <= 255; ++i )
v56[i] = ret_1;
for ( j = 0; j <= 255; ++j )
*((_DWORD *)v56 + j + 512) = 1;
*HeapArray = (__int64)v56;
v57 = malloc(0xC00uLL);
for ( k = 0; k <= 255; ++k )
v57[k] = buf_to_ptr;
for ( m = 0; m <= 255; ++m )
*((_DWORD *)v57 + m + 512) = 2;
HeapArray[1] = (__int64)v57;
It setup the HeapArray ( function pointer and some nums )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# HeapArray 0
# +0 (void*) return 1 func * 0x100
# +0x200 (int) 1 * 0x100
# HeapArray 1
# +0 (void*) *ptrPointer = *buf; buf = buf+1; func * 0x100
# +0x200 (int) 2 * 0x100
# HeapArray 2
# +0 (void*) return 1 func * 0x80 (odd index) / (void*) *ptrPointer+=10 * 0x80 (even index)
# +0x200 (int) 4 *1
# +0x204 (int) 3 * 0x100-1
# HeapArray 3
# +0 (void*) *ptrPointer^=0x45, ptrPointer+=1 *0x100
# +0x200 (int) 1 * 0x100
# HeapArray 4
# +0 (void*) ptrPointer-=2 * 0x100
# +0x200 (int) 7 * 0x100
# HeapArray 5
# +0 (void*) print rejected * 0x100
# HeapArray 6
# +0 (void*) print accepted * 0x100
# HeapArray 7 ~ 27
# +0 (void*) --ptrPointer * 0x100
# +0x200 ~ 0x300 = 5
# +0x2XX = 0x8 ~ 0x1b
HeapArray like this.
1
2
3
4
5
6
7
8
Heap = (__int32 *)*HeapArray;
ReturnValue = 1;
while ( ReturnValue )
{
v7 = (__int32 *)HeapArray[Heap[*(char *)ptrPointer + 0x200]];
ReturnValue = (*(__int64 (**)(void))&Heap[2 * *(char *)ptrPointer])();
Heap = v7;
}
and execution routine is like this.
- get number in HeapArray[Heap[0x200+*ptrPointer]]
- call the function in Heap[2 * *ptrPointer]
- update Heap to next
the number array is the idx of the next HeapArray
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0. goto 1
1. get my one input byte to ptr, goto 2
2. *ptr is odd -> *ptr-=10
even -> return 1, goto 3
if *ptr == 0, goto 4
3. xor *ptr with 0x45, ptr++, goto 1
4. ptrPointer-=2, goto 7
5. print rejected
6. print accepted <-- goal
7. if *ptr == XX,ptr-=1,goto 7+1 or 5
8. if *ptr == XX,ptr-=1,goto 8+1 or 5
...
27. if *Ptr == XX, ptr-=1, goto 6 <-- all correct flag
To find the correct XX, I used IDApython.
parse all index ( 0x276, 0x23D .. ), repeat xor and minus 10 if even number.
solve.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
start=0x555555555704
f=ida_funcs.get_func(start)
c=7
flag=''
for ea in Heads(f.start_ea,f.end_ea):
if get_operand_value(ea,1)==0x555555555342:
to=get_operand_value(ea+0x32,1)
idx=get_operand_value(ea+0x4a,0)
value=get_operand_value(ea+0x4a,1)
print(f"{c}: default : {to}, {(idx//4)-0x200}={value}")
c+=1
if ((idx//4-0x200)^0x45) & 1 == 0:
flag+=chr(((idx//4-0x200)^0x45)-10)
else:
flag+=chr(((idx//4-0x200)^0x45))
print(flag[::-1])
If you find the routine well. It was an easy problem