유니티 게임에서 메모리에 접근할 때 팁
유니티로 한정지었지만 다른 앱에서도 비슷하게 접근하면 되지 않을까 하는 생각을 하며 시작.
List.size = List.add(0x18)
List.base = List.add(0x10).readPointer()
List[0] = base.add(0x20)
List<T>의 다음 인덱스 값의 위치는 T의 필드 크기에 따라 달라지는 듯
List<int> → 4
List<Object> → Object의 필드 크기
Example 1)
List<int\> m_list; // m_list의 인덱스 크기는 4 (int) int id;size = m_list.add(0x18) = 2 라면
base = m_list.add(0x10).readPointer()first_index = base.add(0x20);
second_index = base.add(0x24);for 문으로 정리하면
for (var i=0; i<size; i++) { var id = base.add(0x4 * i).add(0x20); console.log('[+] id : ' + id); }
Example 2)
List<Item\> m_list; // m_list의 인덱스 크기는 0x10 (int + int + int + int) class Item { int Type, int Id, int Value, int Tm; }size = m_list.add(0x18) = 4 라면
base = m_list.add(0x10).readPointer() = 첫번째 Itemm_list[0].Type = m_list.add(0x10).readPointer().add(0x20);
m_list[0].Id = m_list.add(0x10).readPointer().add(0x24);
m_list[0].Value = m_list.add(0x10).readPointer().add(0x28);
m_list[0].Tm = m_list.add(0x10).readPointer().add(0x2C);m_list[1].Type = m_list.add(0x10).readPointer().add(0x10).add(0x20);
m_list[1].Id = m_list.add(0x10).readPointer().add(0x10).add(0x24);
m_list[1].Value = m_list.add(0x10).readPointer().add(0x10).add(0x28);
m_list[1].Tm = m_list.add(0x10).readPointer().add(0x10).add(0x2C);...
배열은 일단 정확하진 않음 → 값은 0x20 부터 존재함
Example 3)
S_Object[] m_obj; // m_obj의 인덱스 크기는 8 (int + int) class S_Object { int Id, int Value; }m_obj.size = m_obj.add(0x18) = 3 이라면
m_obj[0]= m_obj.add(0x20);
m_obj[0].Id= m_obj.add(0x20);
m_obj[0].Value = m_obj.add(0x24);m_obj[1] = m_obj.add(0x8).add(0x20);
m_obj[1].Id = m_obj.add(0x8).add(0x20);
m_obj[1].Value = m_obj.add(0x8).add(0x24);m_obj[2] = m_obj.add(0x10).add(0x20);
m_obj[2].Id = m_obj.add(0x10).add(0x20);
m_obj[2].Value = m_obj.add(0x10).add(0x24);
필드 접근은 offset 이 바로 보여서 쉬운데 프로퍼티에는 어떻게 접근하냐?
→ 프로퍼티는 IDA 에서 함수 형태로 나와있어서 class$$get_property 를 IDA 로 확인해보면 class + offset 을 리턴하는 것을 볼 수 있고, 나중에 해당 offset 으로 접근하면 된다.
Example)
class Obj { ... public int id { get { return 0; } set { } } } Obj obj;
Obj$$get_id 를 IDA로 확인해보면 return Obj + offset; 확인 가능
따라서 id = obj.add(offset);
여기는 25.11.18 에 추가. 엔트리에 key 와 value 가 존재한다.
26.06.09 내용 추가
struct Entry {
int hashCode; // 4
int next; // 4
TKey key; // sizeof(TKey)
TValue value; // sizeof(TValue)
}
public Dictionary<eType, float> TestDict; // enum eType = int
base = TestDict;
size = base.add(0x20).readInt();
entries = base.add(0x18).readPointer();
entriesData = entries.add(0x20);
entries[0].hashCode = entriesData.add(0x10 * 0).add(0x0); // int
entries[0].next = entriesData.add(0x10 * 0).add(0x4); // int
entries[0].key = entriesData.add(0x10 * 0).add(0x8); // int
entries[0].value = entriesData.add(0x10 * 0).add(0xC); // float
entries[1].hashCode = entriesData.add(0x10 * 1).add(0x0); // int
entries[1].next = entriesData.add(0x10 * 1).add(0x4); // int
entries[1].key = entriesData.add(0x10 * 1).add(0x8); // int
entries[1].value = entriesData.add(0x10 * 1).add(0xC); // float
...
public Dictionary<eType, Object> TestDict2;
base = TestDict2;
...
entries = base.add(0x18).readPointer();
entriesData = entries.add(0x20);
entries[0].hashCode = entriesData.add(0x18 * 0).add(0x0); // int
entries[0].next = entriesData.add(0x18 * 0).add(0x4); // int
entries[0].key = entriesData.add(0x18 * 0).add(0x8); // int
entries[0].value = entriesData.add(0x18 * 0).add(0x10); // pointer
...
const dict = args[3]; // Dictionary<int, long>
const count = dict.add(0x20).readS32();
const entries = dict.add(0x18).readPointer();
console.log("[Dict<int,long>] count =", count);
console.log("[Dict<int,long>] entries =", entries);
if (!entries.isNull()) {
const entriesData = entries.add(0x20);
for (let i = 0; i < count; i++) {
const entry = entriesData.add(0x18 * i);
const hashCode = entry.add(0x0).readS32();
const next = entry.add(0x4).readS32();
const key = entry.add(0x8).readS32();
const value = entry.add(0x10).readS64();
if (hashCode < 0) continue;
console.log("---- entry[" + i + "] ----");
console.log("hashCode =", hashCode);
console.log("next =", next);
console.log("key =", key);
console.log("value =", value.toString());
}
}
12월에 업로드 해야지 생각했다가 깜빡하고 이제서야 올림..
암튼 나중에 유용하게 써먹을듯