add send modify

This commit is contained in:
yincong
2025-12-12 17:04:48 +08:00
parent 0a5e4d16be
commit 2e214f2db6
5 changed files with 110 additions and 83 deletions
+2 -1
View File
@@ -3,4 +3,5 @@ __handlers__
*.sqlite
.DS_Store
diaphora_batch*
data
data
.venv
+21 -10
View File
@@ -1,15 +1,26 @@
装填数据,发到jobqueue是他们的目地,我感觉重点是在这里
sub_1032003B0 -> sub_1024803E4 -> sub_1024C6354 可能是统一入口
sub_10237997C image_handler.cc
sub_1023E73E8 text_handler.cc
sub_102363BB0 file_handler.cc
sub_100400950 装填消息
键盘事件触发
sub_10064DD2C 里面有铭文的数据,看看怎么把这个数据传输到下层,估计是
sub_100662CC4 处理消息的关键函数
sub_100662CC4 -> sub_100668580 -> sub_10064DD2C
sub_100662CC4 -> sub_10063F318 -> sub_1006DDDBC 处理发送消息结构体
sub_1006DDDBC 消息体在这个函数
真正的发送阶段
sub_10250D878 是整体的发消息入口有多个阶段来自这里
StartSendMessageSerial sub_1024C4CB4
CoSendMessageWithUploadInfo sub_1023E8108
CoAddSendMessageToDb sub_1023C09D0
CoPrepareShowSendMessage sub_1023BC4E0
sub_1024C7FB4 -> sub_102481CA0 -> sub_105268848
sub_1024C7FB4 sendMessage 入口
sub_10237997C image_handler.cc
sub_1023E73E8 text_handler.cc
sub_102363BB0 file_handler.cc
sub_1024C6354 可能是统一入口
sub_100400950 装填消息
sub_1024C7FB4 sendMessage 入口
+14 -17
View File
@@ -7,16 +7,13 @@ def is_printable_string(data):
if not data:
return False, ""
# 检查是否以null结尾
if data[-1] != 0:
return False, ""
# 检查所有字符是否可打印
result = ""
for byte in data[:-1]: # 排除结尾的null
if 32 <= byte <= 126: # 可打印ASCII
result += chr(byte)
else:
print(f"不可打印字符: {chr(byte)}")
return False, ""
return True, result
@@ -29,8 +26,7 @@ def dereference_recursive(traceMap, addr, struct_size, depth=0, max_depth=5):
:param depth: 当前递归深度
:param max_depth: 最大递归深度
"""
mapAddr = f"0x{addr:016X}"
print(f"mapAddr: {mapAddr}")
mapAddr = f"0x{addr:X}"
traceMap[mapAddr] = {}
if depth >= max_depth:
print(" " * depth + f"[达到最大递归深度 {max_depth}]")
@@ -58,7 +54,7 @@ def dereference_recursive(traceMap, addr, struct_size, depth=0, max_depth=5):
is_str, str_val = is_printable_string(data)
if is_str and len(str_val) > 0:
data[addr][str_val] = {}
traceMap[mapAddr][str_val] = {}
print(f"{indent}字符串: \"{str_val}\"")
return
except:
@@ -71,20 +67,23 @@ def dereference_recursive(traceMap, addr, struct_size, depth=0, max_depth=5):
hex_line = indent + " "
ascii_line = indent + " "
all_ascii_line = ""
for i in range(bytes_to_show):
if i > 0 and i % 16 == 0:
print(f"{hex_line} {ascii_line}")
# print(f"{hex_line} {ascii_line}")
hex_line = indent + " "
ascii_line = indent + " "
byte = ida_bytes.get_byte(addr + i)
hex_line += f"{byte:02X} "
ascii_line += chr(byte) if 32 <= byte <= 126 else "."
all_ascii_line += chr(byte) if 32 <= byte <= 126 else "."
# 打印最后一行
if hex_line.strip():
print(f"{hex_line:50} {ascii_line}")
# if hex_line.strip():
# print(f"{hex_line:50} {ascii_line}")
print(f"地址 0x{addr:X} ascii {all_ascii_line}")
except Exception as e:
print(f"{indent}读取内存失败: {e}")
return
@@ -99,12 +98,9 @@ def dereference_recursive(traceMap, addr, struct_size, depth=0, max_depth=5):
try:
ptr_value = ida_bytes.get_qword(cur_addr)
print(f"{indent}指针[{i}] @ 0x{cur_addr:X} -> 0x{ptr_value:X}")
if ptr_value != 0 and ptr_value != cur_addr:
print(f"{indent}可能是指针,指向: 0x{ptr_value:X}")
nextAddr = f"0x{ptr_value:016X}"
print(f"nextAddr: {nextAddr}")
if 0X00000001019013F4 < ptr_value < 0x7FFFFFFFFFFFFFFF and ptr_value != cur_addr:
print(f"{indent}指针[{i}] @ 0x{cur_addr:X} -> 0x{ptr_value:X}")
nextAddr = f"0x{ptr_value:X}"
traceMap[mapAddr][nextAddr] = {}
dereference_recursive(traceMap[mapAddr], ptr_value, struct_size, depth + 1, max_depth)
@@ -139,6 +135,7 @@ def print_register_struct(reg_name, struct_size=64, max_depth=3):
except Exception as e:
print(f"错误: {e}")
print(f"{reg_name}递归分析结果:")
print(json.dumps(traceMap, indent=4))
@@ -198,4 +195,4 @@ analyze_all_args()
example_usage()
"""
print_register_struct("X0", 64, 3)
print_register_struct("X27", 64, 5)
+43 -55
View File
@@ -1,68 +1,56 @@
# IDAPython Breakpoint Action Script
import idc
import ida_dbg
import idautils
import ida_idd
import ida_name
# ----------------------------------------------------
# 步骤 1: 定义获取和打印堆栈的函数
# ----------------------------------------------------
def print_call_stack():
"""获取当前的调用堆栈地址,并将其打印到 IDA 消息窗口。"""
def dbg_get_call_stack() -> list[dict[str, str]]:
"""Get the current call stack."""
callstack = []
try:
tid = ida_dbg.get_current_thread()
trace = ida_idd.call_stack_t()
# 获取当前线程 ID,通常是获取堆栈的第一步
tid = idc.get_current_thread()
if tid == -1:
print("[!] 脚本错误: 无法获取当前线程 ID。")
return
if not ida_dbg.collect_stack_trace(tid, trace):
return []
for frame in trace:
frame_info = {
"address": hex(frame.callea),
}
try:
module_info = ida_idd.modinfo_t()
if ida_dbg.get_module_info(frame.callea, module_info):
frame_info["module"] = os.path.basename(module_info.name)
else:
frame_info["module"] = "<unknown>"
print("=" * 40)
print(f"✅ 断点触发于地址: 0x{idc.get_screen_ea():X}")
print(f"➡️ **调用堆栈 (Call Stack) 地址:**")
name = (
ida_name.get_nice_colored_name(
frame.callea,
ida_name.GNCN_NOCOLOR
| ida_name.GNCN_NOLABEL
| ida_name.GNCN_NOSEG
| ida_name.GNCN_PREFDBG,
)
or "<unnamed>"
)
frame_info["symbol"] = name
# idautils.get_current_caller_frame() 可获取调用堆栈信息
# 它返回一个列表,其中每个元素都是一个 (返回地址, 帧指针/栈指针) 的元组。
except Exception as e:
frame_info["module"] = "<error>"
frame_info["symbol"] = str(e)
# 遍历堆栈帧并打印返回地址
frame_count = 0
callstack.append(frame_info)
# 注意: 在 64 位 ARM (AArch64) 上,栈操作可能与 x86 不同
# 我们使用 idautils.get_call_stack 尝试获取更标准的堆栈信息。
# idautils.get_call_stack() 可能会返回一系列的 (地址, 描述) 元组
stack_info = ida_dbg.collect_stack_trace()
except Exception as e:
pass
return callstack
if stack_info:
for frame_count, (return_address, _) in enumerate(stack_info):
# 获取函数名(如果有的话)
func_name = idc.get_func_name(return_address)
# 如果函数名获取失败或地址在外部库,则使用原始地址
if not func_name or func_name.startswith("loc_"):
name = ""
else:
name = f" <{func_name}>"
print(f" [{frame_count:02d}] 0x{return_address:X}{name}")
else:
# 如果 idautils.get_call_stack 失败,尝试使用更底层的方法(不推荐,但作为备选)
# 实际调试中,推荐依赖 IDA 调试器自动提供的堆栈视图。
print(" [!] 警告: 自动堆栈追踪失败,请检查 IDA Stack View.")
print(f" --- 堆栈深度: {frame_count + 1} 层 ---")
print("=" * 40)
def dbg_print_call_stack(callstack: list[dict[str, str]]):
print("Call Stack:----------------------------------------")
for i, frame in enumerate(reversed(callstack)):
print(f"{i}: {frame['module']}.{frame['symbol']} @ {frame['address']}")
# ----------------------------------------------------
# 步骤 2: 调用主函数
# ----------------------------------------------------
# 在断点被命中时,执行堆栈打印
print_call_stack()
# ----------------------------------------------------
# 步骤 3: 控制程序流 (重要!)
# ----------------------------------------------------
# 要让程序在打印堆栈后继续执行,必须返回 0 或不返回 (即让 IDA 默认继续)。
# 但是,如果希望程序在打印后暂停 (即执行普通断点的动作),则返回 1 (但这不是本脚本的目的)。
# 如果你想继续执行(Trace Breakpoint),请确保 Action 下一步是 Resume
return 0
dbg_print_call_stack(dbg_get_call_stack())
+30
View File
@@ -0,0 +1,30 @@
import ida_dbg
import ida_idaapi
import ida_bytes
def dbg_bpt(ea):
# 获取X22寄存器的值(指向的内存地址)
x22_value = ida_dbg.get_reg_val("X22")
if x22_value != ida_idaapi.BADADDR:
# 要写入的数据:'1','2','3' 的ASCII码
patch_data = [ord('1'), ord('2'), ord('3')]
# 修改内存
for i, byte_val in enumerate(patch_data):
ida_bytes.patch_byte(x22_value + i, byte_val)
print(f"[断点 0x{ea:X}] 已将 X22(0x{x22_value:X}) 的前3字节修改为 '123'")
# 可选:显示修改前后的内容对比
original = []
for i in range(3):
original.append(ida_bytes.get_byte(x22_value + i))
print(f" 修改前: {[hex(b) for b in original]}")
print(f" 修改后: {[hex(b) for b in patch_data]}")
# 返回0继续执行
return 0
dbg_bpt(0x1006DDE30)