__int64 __fastcall main(int a1, char **a2, char **a3)
{
FILE *v4; // [rsp+0h] [rbp-10h]
FILE *stream; // [rsp+8h] [rbp-8h]
v4 = fopen("secretMessage.raw", "rb");
stream = fopen("secretMessage.enc", "wb");
encode(v4, stream);
remove("secretMessage.raw");
puts("done!");
fclose(stream);
fclose(v4);
return 0LL;
}
encode 함수를 역연산하여 raw를 얻어야 한다.
__int64 __fastcall encode(FILE *a1, FILE *a2)
{
unsigned __int8 v3; // [rsp+17h] [rbp-9h]
int c; // [rsp+18h] [rbp-8h]
int v5; // [rsp+1Ch] [rbp-4h]
if ( a1 && a2 )
{
v5 = -1;
v3 = 0;
while ( 1 )
{
c = fgetc(a1);
if ( c == -1 )
return 0LL;
fputc(c, a2);
if ( c == v5 )
{
v3 = 0;
while ( 1 )
{
c = fgetc(a1);
if ( c == -1 )
break;
if ( c != v5 )
{
fputc(v3, a2);
fputc(c, a2);
v5 = c;
break;
}
if ( ++v3 == 0xFF )
{
fputc(255, a2);
v5 = -1;
break;
}
}
}
else
{
v5 = c;
}
if ( c == -1 )
{
fputc(v3, a2);
return 0LL;
}
}
}
else
{
*__errno_location() = 2;
return 0xFFFFFFFFLL;
}
}
여기서 핵심은
v5 = -1;
v3 = 0;
while ( 1 )
{
c = fgetc(a1);
if ( c == -1 )
return 0LL;
fputc(c, a2);
if ( c == v5 )
{
v3 = 0;
while ( 1 )
{
c = fgetc(a1);
if ( c == -1 )
break;
if ( c != v5 )
{
fputc(v3, a2);
fputc(c, a2);
v5 = c;
break;
}
if ( ++v3 == 0xFF )
{
fputc(255, a2);
v5 = -1;
break;
}
}
}
else
{
v5 = c;
}
if ( c == -1 )
{
fputc(v3, a2);
return 0LL;
}
}
일단 raw에서 읽은 값을 enc에 저장하고 이전의 값과 동일하다면 동일한 갯수를 쓰고 해당 값을 한 번 더 써서 마무리한다. 이때 갯수의 최대값은 255다. 그리고 255의 경우에는 문자를 한 번 더 쓰지 않는다.
A B B 10 C -> B가 12개 연속함
A B B 255 B B 2 C -> B가 261개 연속함
with open('D:\\code\\dh\\rev\\secretmsg\\secretMessage.enc', 'rb') as f:
raw = open('D:\\code\\dh\\rev\\secretmsg\\secretMessage.raw', 'wb')
data = f.read()
idx = 0
while idx < len(data):
c = data[idx]
if ((idx + 1) < len(data)) and c == data[idx+1]:
for i in range(data[idx+2]+2):
raw.write(bytes([c]))
idx += 3
else:
raw.write(bytes([c]))
idx += 1
raw.close()