Skip to content

Commit d7b6353

Browse files
committed
add manual patching script and flask server
1 parent 4ef7471 commit d7b6353

File tree

4 files changed

+452
-0
lines changed

4 files changed

+452
-0
lines changed

root-module-manual/main.py

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import logging
2+
import os
3+
import re
4+
import shutil
5+
import subprocess
6+
import sys
7+
import zipfile
8+
9+
# Define color codes for logging
10+
class LogColors:
11+
HEADER = '\033[95m'
12+
OKBLUE = '\033[94m'
13+
OKCYAN = '\033[96m'
14+
OKGREEN = '\033[92m'
15+
WARNING = '\033[93m'
16+
FAIL = '\033[91m'
17+
ENDC = '\033[0m'
18+
BOLD = '\033[1m'
19+
UNDERLINE = '\033[4m'
20+
21+
# Custom logging formatter to include colors
22+
class ColoredFormatter(logging.Formatter):
23+
def format(self, record):
24+
log_colors = {
25+
'DEBUG': LogColors.OKCYAN,
26+
'INFO': LogColors.OKGREEN,
27+
'WARNING': LogColors.WARNING,
28+
'ERROR': LogColors.FAIL,
29+
'CRITICAL': LogColors.FAIL + LogColors.BOLD
30+
}
31+
log_color = log_colors.get(record.levelname, LogColors.ENDC)
32+
record.msg = f"{log_color}{record.msg}{LogColors.ENDC}"
33+
return super().format(record)
34+
35+
def run_command(command):
36+
"""
37+
Runs a shell command and logs the output.
38+
39+
Args:
40+
command (str): The command to run.
41+
42+
Returns:
43+
str: The standard output from the command.
44+
45+
Raises:
46+
SystemExit: If the command fails.
47+
"""
48+
logging.info(f"Running command: {command}")
49+
result = subprocess.run(command, shell=True, capture_output=True, text=True)
50+
if result.returncode != 0 and "Cannot determine entrypoint" not in result.stderr:
51+
logging.error(f"Command failed: {command}\n{result.stderr}")
52+
sys.exit(1)
53+
logging.info(f"Command output: {result.stdout}")
54+
return result.stdout
55+
56+
def get_symbol_address(file_path, symbol_name):
57+
"""
58+
Gets the address of a symbol in a binary file using radare2.
59+
60+
Args:
61+
file_path (str): The path to the binary file.
62+
symbol_name (str): The name of the symbol to find.
63+
64+
Returns:
65+
str: The address of the symbol.
66+
67+
Raises:
68+
SystemExit: If the symbol is not found.
69+
"""
70+
logging.info(f"Getting address for symbol: {symbol_name}")
71+
output = run_command(f"radare2 -q -e bin.cache=true -c 'is~{symbol_name}' -z {file_path}")
72+
match = re.search(r'0x[0-9a-fA-F]+', output)
73+
if match:
74+
address = match.group(0)
75+
logging.info(f"Found address for {symbol_name}: {address}")
76+
return address
77+
else:
78+
logging.error(f"Symbol {symbol_name} not found in {file_path}")
79+
sys.exit(1)
80+
81+
def patch_address(file_path, address, patch_bytes):
82+
"""
83+
Patches a specific address in a binary file with given bytes using radare2.
84+
85+
Args:
86+
file_path (str): The path to the binary file.
87+
address (str): The address to patch.
88+
patch_bytes (str): The bytes to write at the address.
89+
90+
Raises:
91+
SystemExit: If the patching command fails.
92+
"""
93+
logging.info(f"Patching address {address} with bytes: {patch_bytes}")
94+
run_command(f"radare2 -q -e bin.cache=true -w -c 's {address}; wx {patch_bytes}; wci' {file_path}")
95+
logging.info(f"Successfully patched address {address}")
96+
97+
def copy_file_to_src(file_path):
98+
"""
99+
Copies a file to the 'src/' directory.
100+
101+
Args:
102+
file_path (str): The path to the file to copy.
103+
"""
104+
src_dir = 'src/'
105+
if not os.path.exists(src_dir):
106+
os.makedirs(src_dir)
107+
shutil.copy(file_path, src_dir)
108+
logging.info(f"Copied {file_path} to {src_dir}")
109+
110+
def zip_src_files():
111+
"""
112+
Zips all files in the 'src/' directory into 'btl2capfix.zip', preserving symlinks.
113+
"""
114+
with zipfile.ZipFile('btl2capfix.zip', 'w', zipfile.ZIP_DEFLATED, allowZip64=True) as zipf:
115+
for root, dirs, files in os.walk('src/'):
116+
for file in files:
117+
file_path = os.path.join(root, file)
118+
if file_path == os.path.join('src', os.path.basename(file_path)):
119+
continue # Skip the original uploaded file
120+
if os.path.islink(file_path):
121+
link_target = os.readlink(file_path)
122+
zip_info = zipfile.ZipInfo(os.path.relpath(file_path, 'src/'))
123+
zip_info.create_system = 3 # Unix
124+
zip_info.external_attr = 0o777 << 16
125+
zip_info.external_attr |= 0xA000
126+
zipf.writestr(zip_info, link_target)
127+
else:
128+
zipf.write(file_path, os.path.relpath(file_path, 'src/'))
129+
logging.info("Zipped files under src/ into btl2capfix.zip")
130+
131+
def main():
132+
"""
133+
Main function to execute the script. It performs the following steps:
134+
1. Copies the input file to the 'src/' directory.
135+
2. Patches specific addresses in the binary file.
136+
3. Zips the files in the 'src/' directory into 'btl2capfix.zip'.
137+
"""
138+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
139+
logger = logging.getLogger()
140+
handler = logger.handlers[0]
141+
handler.setFormatter(ColoredFormatter('%(asctime)s - %(levelname)s - %(message)s'))
142+
143+
if len(sys.argv) != 2:
144+
logging.error("Usage: python main.py <file_path>")
145+
sys.exit(1)
146+
147+
file_path = sys.argv[1]
148+
149+
# Patch l2c_fcr_chk_chan_modes
150+
l2c_fcr_chk_chan_modes_address = get_symbol_address(file_path, "l2c_fcr_chk_chan_modes")
151+
patch_address(file_path, l2c_fcr_chk_chan_modes_address, "20008052c0035fd6")
152+
153+
# Patch l2cu_send_peer_info_req
154+
l2cu_send_peer_info_req_address = get_symbol_address(file_path, "l2cu_send_peer_info_req")
155+
patch_address(file_path, l2cu_send_peer_info_req_address, "c0035fd6")
156+
157+
# Copy file to src/
158+
copy_file_to_src(file_path)
159+
160+
# Zip files under src/
161+
zip_src_files()
162+
163+
if __name__ == "__main__":
164+
main()

0 commit comments

Comments
 (0)