forked from 4z0t/SCFA-python-patcher
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add statistics and introduce new hook format (#4)
- Loading branch information
Showing
15 changed files
with
70,040 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
During REing you will notice certain patterns. | ||
|
||
## Object ctor and dtor | ||
|
||
These patterns will help with noticing certain structures when REing code. | ||
|
||
### std::vector | ||
|
||
In ctor you won't notice it at first glance. However if you look closely: | ||
|
||
```cpp | ||
... | ||
*(_DWORD *)(a + 1) = 0; | ||
*(_DWORD *)(a + 2) = 0; | ||
*(_DWORD *)(a + 3) = 0; | ||
... | ||
``` | ||
You'll notice that `*a` wasn't set to anything, and if you find dtor: | ||
```cpp | ||
... | ||
if(*(a + 1)) | ||
{ | ||
... | ||
free(*(_DWORD *)(a + 1)); // or operator delete(*(a + 1)); | ||
} | ||
*(_DWORD *)(a + 1) = 0; | ||
*(_DWORD *)(a + 2) = 0; | ||
*(_DWORD *)(a + 3) = 0; | ||
... | ||
``` | ||
This is a definitely std::vector and function before free (if it presents) may suggest you the type of vector. | ||
|
||
```cpp | ||
... | ||
if(a->v.begin) | ||
{ | ||
... | ||
free(a->v.begin); // or operator delete(*(a + 1)); | ||
} | ||
a->v.begin = 0; | ||
a->v.end = 0; | ||
a->v.capacity_end = 0; | ||
... | ||
``` | ||
|
||
**Note: offsets may be different, but overall idea stays** | ||
|
||
An example: | ||
|
||
```cpp | ||
v2 = *(std::string **)(a1 + 8); | ||
if ( v2 ) | ||
{ | ||
func_FreeStringsRange(v2, *(std::string **)(a1 + 12)); | ||
operator delete(*(void **)(a1 + 8)); | ||
} | ||
*(_DWORD *)(a1 + 8) = 0; | ||
*(_DWORD *)(a1 + 12) = 0; | ||
*(_DWORD *)(a1 + 16) = 0; | ||
``` | ||
This is a vector of std::string. | ||
### linked list | ||
ctor | ||
```cpp | ||
*(_DWORD *)(a1 + 4) = a1 + 4; | ||
*(_DWORD *)(a1 + 8) = a1 + 4; | ||
``` | ||
|
||
dtor | ||
```cpp | ||
*(_DWORD *)(*(_DWORD *)(a1 + 4) + 4) = *(_DWORD *)(a1 + 8); | ||
**(_DWORD **)(a1 + 8) = *(_DWORD *)(a1 + 4); | ||
*(_DWORD *)(a1 + 4) = a1 + 4; | ||
*(_DWORD *)(a1 + 8) = a1 + 4; | ||
``` | ||
|
||
This is a linked list | ||
|
||
```cpp | ||
a1->l.prev = &a1->l; | ||
a1->l.next = &a1->l; | ||
``` | ||
|
||
```cpp | ||
a1->l.next->prev = a1->l.prev; | ||
a1->l.prev->next = a1->l.next; | ||
a1->l.prev = &a1->l; | ||
a1->l.next = &a1->l; | ||
``` | ||
|
||
### std::map (binary tree) | ||
|
||
```cpp | ||
v1 = sub_465480(); // this function has weird stuff and call to *new* with size we'll use later | ||
// no first field set | ||
*((_DWORD *)this + 1) = v1; // doing some stuff with the second field | ||
*(_BYTE *)(v1 + 45/*any offset*/) = 1; // setting some value to 1 | ||
*(_DWORD *)(*((_DWORD *)this + 1) + 4) = *((_DWORD *)this + 1); | ||
**((_DWORD **)this + 1) = *((_DWORD *)this + 1); | ||
*(_DWORD *)(*((_DWORD *)this + 1) + 8) = *((_DWORD *)this + 1); | ||
*((_DWORD *)this + 2) = 0; // setting third field to zero | ||
``` | ||
|
||
This is a map based on binary tree. | ||
|
||
```cpp | ||
node = create_node(); | ||
this->m.root = node; | ||
node->is_leaf = 1; | ||
this->m.root->parent = this->m.root; | ||
this->m.root->left = this->m.root; | ||
this->m.root->right = this->m.root; | ||
this->m.size = 0; | ||
``` | ||
|
||
Where dtor will look very fancy and you'll guess it very fast | ||
|
||
```cpp | ||
... // maybe an iteration over map before | ||
some_function(&this->m, &node, this->m.root->left, this->m.root); | ||
operator delete(this->m.root); | ||
this->m.root = 0; | ||
this->m.size = 0; | ||
... | ||
``` | ||
### std::shared_ptr | ||
```cpp | ||
if ( v10 ) | ||
{ | ||
if ( !_InterlockedExchangeAdd(v10 + 1, 0xFFFFFFFF) ) | ||
{ | ||
(*(void (__thiscall **)(volatile signed __int32 *))(*v10 + 4))(v10); | ||
if ( !_InterlockedExchangeAdd(v10 + 2, 0xFFFFFFFF) ) | ||
(*(void (__thiscall **)(volatile signed __int32 *))(*v10 + 8))(v10); | ||
} | ||
} | ||
``` | ||
You'll see this very frequently. It is inlined dtor of shared pointer. So if `v10` is a counter block, then field before it is pointer to data associated with it. | ||
|
||
```cpp | ||
if ( pi ) | ||
{ | ||
if ( !_InterlockedExchangeAdd(&pi->use_count_, 0xFFFFFFFF) ) | ||
{ | ||
pi->vtable->dispose(pi); | ||
if ( !_InterlockedExchangeAdd(&pi->weak_count_, 0xFFFFFFFF) ) | ||
pi->vtable->destroy(pi); | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
We are looking for experienced reverse engineers to improve SCFA's engine and expand it's functions. | ||
Right now we are having goal to improve and expose some of the UI's functionality to have more control over it in Lua. | ||
Specifically user's input and what user can see in UI. | ||
|
||
There are 2 main fields where we need help: | ||
|
||
* Reverse engineering: revesing | ||
* structures and classes of engine and their names | ||
* functions' logic and their names | ||
* Engine recreation: with given decompiled parts of engine | ||
* recreate functions in C/C++ | ||
* recreate structures and classes in C/C++ | ||
* recreate generic structures and algorithms in C/C++ | ||
|
||
Tooling: | ||
|
||
* C/C++ | ||
* GCC inline x86 asm | ||
* IDA + x64dbg | ||
* a bit of Lua + its API | ||
|
||
Dedicated repositories: | ||
|
||
* [C++ patcher](https://github.com/FAForever/FA_Patcher) | ||
* [Python patcher](https://github.com/4z0t/SCFA-python-patcher) | ||
* [Game's executable patches](https://github.com/FAForever/FA-Binary-Patches) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
import sys | ||
import time | ||
import Patcher | ||
import patcher | ||
|
||
if __name__ == "__main__": | ||
start = time.time() | ||
Patcher.patch(*sys.argv) | ||
patcher.patch(*sys.argv) | ||
end = time.time() | ||
print(f"Patched in {end-start:.2f}s") |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import re | ||
from pathlib import Path | ||
|
||
ADDRESS_RE = re.compile(r"^(0[xX][0-9A-Fa-f]{6,8})\:$") | ||
FUNCTION_NAME_RE = re.compile(r"@([a-zA-Z\_][a-zA-Z0-9\_]+)") | ||
|
||
|
||
class Section: | ||
|
||
def __init__(self, address: str, lines: list[str]) -> None: | ||
self._address: str = address | ||
self._lines: list[str] = lines | ||
|
||
def lines_to_cpp(self): | ||
s = "" | ||
for line in self._lines: | ||
line = line.translate(str.maketrans({"\"": r"\"", "\\": r"\\", })) | ||
|
||
if FUNCTION_NAME_RE.findall(line): | ||
line = FUNCTION_NAME_RE.subn(r'"QU(\1)"', line)[0] | ||
|
||
s += f'"{line};"\n' | ||
return s | ||
|
||
def to_cpp(self, index: int) -> str: | ||
if self._address is None: | ||
return self.lines_to_cpp() | ||
return f'SECTION({index:X}, {self._address})\n{self.lines_to_cpp()}' | ||
|
||
|
||
class Hook: | ||
def __init__(self, sections: list[Section]) -> None: | ||
self._sections: list[Section] = sections | ||
|
||
def to_cpp(self): | ||
s = '#include "../asm.h"\n#include "../define.h"\n' | ||
if len(self._sections) > 0: | ||
sections_lines = (section.to_cpp(i).split("\n") | ||
for i, section in enumerate(self._sections)) | ||
s += f"asm(\n{''.join((f" {line}\n" for lines in sections_lines for line in lines))});" | ||
return s | ||
|
||
|
||
def load_hook(file_path: Path) -> Hook: | ||
sections: list[Section] = [] | ||
lines = [] | ||
address = None | ||
with open(file_path) as f: | ||
for line in f.readlines(): | ||
# remove comments | ||
line = line.split("//")[0] | ||
line = line.split("#")[0] | ||
line = line.strip() | ||
if not line: | ||
continue | ||
|
||
if match := ADDRESS_RE.match(line): | ||
if len(lines) > 0: | ||
sections.append(Section(address, lines)) | ||
lines = [] | ||
address = match.group(1) | ||
continue | ||
lines.append(line) | ||
if len(lines) > 0: | ||
sections.append(Section(address, lines)) | ||
return Hook(sections) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .Patcher import patch |
File renamed without changes.
Oops, something went wrong.