841 words
4 minutes
[DreamHack] dungeon-in-1983
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
int i; // [rsp+14h] [rbp-1BCh]
char *lineptr; // [rsp+18h] [rbp-1B8h] BYREF
size_t ptr; // [rsp+20h] [rbp-1B0h] BYREF
FILE *stream; // [rsp+28h] [rbp-1A8h]
__int64 v8[2]; // [rsp+30h] [rbp-1A0h] BYREF
int v9; // [rsp+40h] [rbp-190h]
__int64 v10; // [rsp+44h] [rbp-18Ch]
__int64 v11; // [rsp+4Ch] [rbp-184h]
int v12; // [rsp+54h] [rbp-17Ch]
__int64 v13; // [rsp+58h] [rbp-178h]
__int64 v14; // [rsp+60h] [rbp-170h]
int v15; // [rsp+68h] [rbp-168h]
__int64 v16; // [rsp+6Ch] [rbp-164h]
__int64 v17; // [rsp+74h] [rbp-15Ch]
int v18; // [rsp+7Ch] [rbp-154h]
__int64 v19; // [rsp+80h] [rbp-150h]
__int64 v20; // [rsp+88h] [rbp-148h]
int v21; // [rsp+90h] [rbp-140h]
__int64 v22; // [rsp+94h] [rbp-13Ch]
__int64 v23; // [rsp+9Ch] [rbp-134h]
int v24; // [rsp+A4h] [rbp-12Ch]
__int64 v25; // [rsp+A8h] [rbp-128h]
__int64 v26; // [rsp+B0h] [rbp-120h]
int v27; // [rsp+B8h] [rbp-118h]
__int64 v28; // [rsp+BCh] [rbp-114h]
__int64 v29; // [rsp+C4h] [rbp-10Ch]
int v30; // [rsp+CCh] [rbp-104h]
__int64 v31; // [rsp+D0h] [rbp-100h]
__int64 v32; // [rsp+D8h] [rbp-F8h]
int v33; // [rsp+E0h] [rbp-F0h]
__int64 v34; // [rsp+E4h] [rbp-ECh]
__int64 v35; // [rsp+ECh] [rbp-E4h]
int v36; // [rsp+F4h] [rbp-DCh]
char s[200]; // [rsp+100h] [rbp-D0h] BYREF
unsigned __int64 v38; // [rsp+1C8h] [rbp-8h]
v38 = __readfsqword(0x28u);
v8[0] = 0x6B73696C69736142LL;
v8[1] = 0LL;
v9 = 0;
v10 = 0x6172656D696843LL;
v11 = 0LL;
v12 = 0;
v13 = 0x6E656B61724BLL;
v14 = 0LL;
v15 = 0;
v16 = 0x6E6F67726F47LL;
v17 = 0LL;
v18 = 0;
v19 = 0x6F6769646E6557LL;
v20 = 0LL;
v21 = 0;
v22 = 0x727561746F6E694DLL;
v23 = 0LL;
v24 = 0;
v25 = 0x616874616976654CLL;
v26 = 110LL;
v27 = 0;
v28 = 0x6172647948LL;
v29 = 0LL;
v30 = 0;
v31 = 0x726F6369746E614DLL;
v32 = 101LL;
v33 = 0;
v34 = 6516562LL;
v35 = 0LL;
v36 = 0;
sub_130A(a1);
stream = fopen("/dev/urandom", "r");
puts("Welcome to the Dungeon!");
puts("You have only two buttons: A and B.");
puts("Each monster requires certain series of key combinations to be defeated, so be careful!");
for ( i = 0; i <= 9; ++i )
{
fread(&ptr, 8uLL, 1uLL, stream);
printf("[STAGE %2d]: %s\n", (unsigned int)(i + 1), (const char *)v8 + 20 * i);
sub_138D(ptr);
printf("Cast your spell!: ");
fgets(s, 200, stdin);
if ( s[strlen(s) - 1] == 10 )
s[strlen(s) - 1] = 0;
if ( !(unsigned int)sub_1407(s, ptr) )
{
puts("You were defeated. Retreat!");
exit(-1);
}
printf("%s defeated. STAGE %2d cleared!\n", (const char *)v8 + 20 * i, (unsigned int)(i + 1));
}
fclose(stream);
printf("It's dangerous to go alone! Take the flag: ");
lineptr = 0LL;
ptr = 0LL;
stream = fopen("./flag", "r");
getline(&lineptr, &ptr, stream);
printf("%s", lineptr);
free(lineptr);
fclose(stream);
return 0LL;
}
요건 메인이고, 우리가 볼 로직은 function - sub_1407입니다.
_BOOL8 __fastcall sub_1407(__int64 a1, __int64 a2)
{
int v2; // eax
int v4; // [rsp+1Ch] [rbp-14h]
int v5; // [rsp+20h] [rbp-10h]
int i; // [rsp+24h] [rbp-Ch]
__int64 v7; // [rsp+28h] [rbp-8h]
v7 = 0LL;
v4 = 0;
v5 = 0;
for ( i = 0; *(_BYTE *)(i + a1); ++i )
{
v2 = *(char *)(i + a1);
if ( v2 == 65 )
{
v5 = 1;
++v7;
if ( v4 )
{
puts("A button stucked! Retreat...");
exit(-1);
}
v4 = 1;
}
else
{
if ( v2 != 66 )
{
puts("Invalid button!");
exit(-1);
}
if ( !v5 )
{
puts("Lore says the spell should start with A...");
exit(-1);
}
v7 *= 2LL;
v4 = 0;
}
}
return v7 == a2;
}
- A가 나오면 결과에 1을 더함
- B가 나오면 결과를 2배로 늘림
뭐 요걸 역연산해서 얻어내는 것이다! 뭐 이렇게 하면됩니다.
딱히 어려운 아이디어는 아닌 것 같아 여기까지만 하겠습니다.
조심조심
63 ~ 48 47 ~ 40 39 ~ 32 31 ~ 24 23 ~ 16 15 ~ 8 7 ~ 0 HIWORD BYTE5 BYTE4 BYTE3 BYTE2 BYTE1 (u_int8)
정답코드
from pwn import *
def solution(input_value):
def parse(input_value: str):
# [INFO]를 없앨거임
input_value = input_value[7:]
input_value = input_value.split(', ')
values = []
print(input_value)
for i in input_value:
print(i)
values.append(int(i.split(': ')[1].replace('\'', '')))
print(values)
# 16bit, 8bit, 8bit, 8bit, 8bit, 8bit, 8bit
# 64bit
result = values[0] << 48
for i in range(1, len(values)): result += values[i] << ((8 * (i-1)))
'''
63 48 47 40 39 32 31 24 23 16 15 8 7 0
+--------+--------+--------+--------+--------+--------+--------+
| HIWORD | BYTE5 | BYTE4 | BYTE3 | BYTE2 | BYTE1 | (u_int8)|
+--------+--------+--------+--------+--------+--------+--------+
요걸 반대로 생각해서 너무 오래걸림
ㅠㅜ
'''
return result
if type(input_value) == bytes:
input_value = str(input_value)[2:]
stack = b''
value = parse(input_value)
print(value)
while value > 1:
if value & 1 == 0:
value >>= 1
stack += b'B'
else:
value -= 1
stack += b'A'
stack += b'A'
return ''.join([chr(i) for i in reversed(stack)])
#
p = remote("host3.dreamhack.games", 14186)
for i in range(10):
result = solution(p.recvline_startswith(b"[INFO] "))
print(result)
p.sendline(result)
# p.interactive()
p.interactive()
[DreamHack] dungeon-in-1983
https://compy07.github.io/Blog/posts/security/crypto/dreamhack/level_1/dungeon-in-1983/