godot reverse engineering

povo·2025년 1월 15일

Reverse Engineering

목록 보기
1/1

1. pck

고도 프로그램은 exe (godot engine)와 pck (packed program resource) 로 이루어져 있다.

pck는 리소스 패키지 파일로 일반적으로 exe와 같은 위치에 존재하지만, 옵션에 따라 exe에 포함시킬 수도 있다.

2. extracting embed-pck

pck 파일엔 magic number가 있기 때문에 exe에서 쉽게 추출할 수 있다.

// Godot's packed file magic header ("GDPC" in ASCII).
#define PACK_HEADER_MAGIC 0x43504447

https://github.com/godotengine/godot/blob/master/core/io/file_access_pack.h

3. pck encryption

고도 엔진에선 컴파일시 encryption 옵션을 통해 데이터를 256비트 aes key로 암호화 할 수 있다.

https://docs.godotengine.org/en/stable/contributing/development/compiling/compiling_with_script_encryption_key.html

고도엔진은 godot/core/io/file_access_encrypted.cpp에 있는 FileAccessEncrypted::open_and_parse_password(Ref p_base, const String &p_key, Mode p_mode) 함수에서 encryption key를 사용한다.

고도엔진은 godot/core/io/file_access_encrypted.cpp에 있는 FileAccessEncrypted::open_and_parse 함수에서 encryption key를 사용한다.

그리고 open_and_parsegodot/core/io/file_access_pack.cppPackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset)에서 호출된다.

key는 이 때 가져온다.

if (enc_directory) {
		Ref<FileAccessEncrypted> fae;
		fae.instantiate();
		ERR_FAIL_COND_V_MSG(fae.is_null(), false, "Can't open encrypted pack directory.");

		Vector<uint8_t> key;
		key.resize(32);
		for (int i = 0; i < key.size(); i++) {
        	// [1] getting encryption key
			key.write[i] = script_encryption_key[i];
		}

		// [2] calling open_and_parse
		Error err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_READ, false);
		ERR_FAIL_COND_V_MSG(err, false, "Can't open encrypted pack directory.");
		f = fae;
	}

https://github.com/godotengine/godot/blob/master/core/io/file_access_pack.cpp
https://github.com/godotengine/godot/blob/master/core/io/file_access_encrypted.cpp#L36

4. finding open_and_parse

내가 풀었던 고도 크랙미 바이너리에서 함수를 찾았다.
함수 내에는 문자열이 포함되어 있어 찾기 쉽다.

v5 = *(this + 384);
  if ( v5 )
  {
    v7 = (*(*v5 + 248i64))(v5, &v62, p_key, p_mode);
    v59 = 0i64;
    v8 = sub_141508654(&v60, "Can't open file while another file from path '", v7);

"Can't open file while another file from path '"
또는
"FileAccessEncrypted::open_and_parse"
를 찾으면 된다.

5. dumping encryption key

p_key를 32바이트 읽으면 encryption key를 구할 수 있다.

000001A5F54E3800  2A 80 B9 0B 20 A1 D1 D5 10 A7 7D 95 42 ED C0 6F  *.¹. ¡ÑÕ.§}.BíÀo  
000001A5F54E3810  5A 6C B2 8D 70 EC 58 57 22 F8 07 10 50 C3 20 DE  Zl².pìXW"ø..PÃ Þ  

6. getting script_encryption_key

또는 try_open_pack에서 script_encryption_key를 찾으면 덤프를 안해도 된다.

문자열:
"Can't open encrypted pack directory."
"PackedSourcePCK::try_open_pack"
를 찾거나 또는 open_and_parse를 호출하는 곳을 찾으면 된다.

x64dbg


위쪽에 jmp가 있고 그쪽으로 따라가면


아래에 script_encryption_key가 보인다.

IDA

위쪽으로 올리면 보인다.

0개의 댓글