PTR、OFFSET、ADDR

本文介绍了在汇编语言中如何使用PTR指定数据尺寸进行操作,OFFSET获取全局变量或标号的偏移地址,ADDR获取变量地址的方法,并对比了OFFSET与ADDR的区别及应用场景。

PTR: 指定要操作的数据尺寸

; Test12_1.asm 
.386 
.model flat, stdcall 
 
include  windows.inc 
include  kernel32.inc 
include  masm32.inc 
include  debug.inc 
includelib kernel32.lib 
includelib masm32.lib 
includelib debug.lib 
 
.data 
   val db 11h, 22h, 33h, 44h, 55h, 66h, 77h, 88h 
 
.code 
main proc 
   xor eax, eax       ;清空 EAX, 同 mov eax, 0 
   mov eax, dword ptr val  ; 
   PrintHex eax       ;44332211 
   
   xor eax, eax       ; 
   mov eax, dword ptr val+1 ; 
   PrintHex eax       ;55443322 
   
   xor eax, eax       ; 
   mov ax, 
word ptr val   ; 
   PrintHex eax       ;00002211 
   
   xor eax, eax       ; 
   mov al, byte ptr val   ; 
   PrintHex eax       ;00000011 
   ret 
main endp 
end main

 

常常这样使用:dword ptr;word ptr;byte ptr;分别指定要操作的数据长度为双字、字。字节。


OFFSET: 获取全局变量或标号的偏移地址

; Test12_2.asm 
.386 
.model flat, stdcall 
 
include  windows.inc 
include  kernel32.inc 
include  masm32.inc 
include  debug.inc 
includelib kernel32.lib 
includelib masm32.lib 
includelib debug.lib 
 
.data 
   v1 db 'abcdefg', 0 
   v2 dd 11223344h 
 
.code 
main proc 
   PrintHex offset v1  ;00403000 
   PrintHex offset v2  ;00403008 
   PrintHex offset main ;00401000 - 这里的 main 是个标号 
   ret 
;本例中的 offset 不能用 addr 代替 
main endp 
end main 

 

ADDR: 类似 offset 也是获取变量的地址...

; Test12_3.asm 
.386 
.model flat, stdcall 
 
;include  windows.inc 
include  kernel32.inc 
includelib kernel32.lib 
include  user32.inc 
includelib user32.lib 
 
.data 
   v1 dd 00434241h ;ABC 
   v2 dd 00636261h ;abc 
 
.code 
main proc 
   invoke MessageBox, 0, offset v1, offset v2, 0 ;现在 v1、v2 是全局变量 
   invoke MessageBox, 0,  addr v2,  addr v1, 0 ;使用 offset 和 addr 均可 
   invoke ExitProcess, 0 
main endp 
end main 

  获取局部变量的地址只能使用 ADDR:

; Test12_4.asm 
.386 
.model flat, stdcall 
 
;include  windows.inc 
include  kernel32.inc 
includelib kernel32.lib 
include  user32.inc 
includelib user32.lib 
 
.code 
main proc 
   LOCAL v1,v2 
   mov v1, 00434241h 
   mov v2, 00636261h 
   ;invoke MessageBox, 0, offset v1, offset v2, 0 ;offset 不能获取局部变量的地址 
   invoke MessageBox, 0,  addr v2,  addr v1, 0 
   invoke ExitProcess, 0 
main endp 
end main 

  OFFSET 和 ADDR 的异同:

  1、offset 不能获取局部变量的地址;

  2、addr 只能用于调用函数(invoke)时, 不能用于赋值操作;

  3、addr 面对局部变量时会转换为 lea 等指令, addr 面对全局变量时则直接调用 offset;

  4、在 invoke 中应尽量使用 addr, 其他只用 offset.

struct task_struct_offset { int16_t pid_offset; int16_t tgid_offset; int16_t thread_pid_offset; int16_t ptracer_cred_offset; int16_t real_cred_offset; int16_t cred_offset; int16_t comm_offset; int16_t fs_offset; int16_t files_offset; int16_t loginuid_offset; int16_t sessionid_offset; int16_t seccomp_offset; int16_t security_offset; int16_t stack_offset; int16_t tasks_offset; int16_t mm_offset; int16_t active_mm_offset; }; int resolve_current() { uint64_t sp_el0, sp; asm volatile("mrs %0, sp_el0" : "=r"(sp_el0)); asm volatile("mov %0, sp" : "=r"(sp)); sp_el0_is_current = 0; sp_el0_is_thread_info = 0; init_task = (struct task_struct *)kallsyms_lookup_name("init_task"); uint64_t init_thread_union_addr = kallsyms_lookup_name("init_thread_union"); if (is_kimg_range(sp_el0)) { if (sp_el0 == init_thread_union_addr) { sp_el0_is_thread_info = 1; } else if ((uint64_t)init_task == sp_el0 || (sp_el0 & (page_size - 1)) || (task_struct_offset.comm_offset = find_swapper_comm_offset(sp_el0, TASK_STRUCT_MAX_SIZE)) > 0) { sp_el0_is_current = 1; init_task = (struct task_struct *)sp_el0; } else { sp_el0_is_thread_info = 1; } } int thread_shift_cand[] = { 14, 15, 16 }; for (int i = 0; i < sizeof(thread_shift_cand) / sizeof(thread_shift_cand[0]); i++) { int tsz = 1 << thread_shift_cand[i]; uint64_t sp_low = sp & ~(tsz - 1); uint64_t psp = sp_low; for (; psp < sp_low + THREAD_INFO_MAX_SIZE; psp += 8) { if (*(uint64_t *)psp == STACK_END_MAGIC) { if (psp == sp_low) { thread_size = tsz; stack_end_offset = 0; thread_info_in_task = 1; } else { thread_size = tsz; stack_end_offset = psp - sp_low; thread_info_in_task = 0; } break; } } } if (!thread_info_in_task) { uint64_t thread_info_addr = (uint64_t)current_thread_info_sp(); if (init_task) { for (uint64_t ptr = thread_info_addr; ptr < thread_info_addr + stack_end_offset; ptr += sizeof(uint64_t)) { uint64_t pv = *(uint64_t *)ptr; if (pv == (uint64_t)init_task) { task_in_thread_info_offset = ptr - thread_info_addr; break; } } } else { for (uint64_t ptr = thread_info_addr; ptr < thread_info_addr + stack_end_offset; ptr += sizeof(uint64_t)) { uint64_t pv = *(uint64_t *)ptr; task_struct_offset.comm_offset = find_swapper_comm_offset(pv, TASK_STRUCT_MAX_SIZE); if (task_struct_offset.comm_offset > 0) { init_task = (struct task_struct *)pv; task_in_thread_info_offset = ptr - thread_info_addr; } } } } if (task_struct_offset.comm_offset <= 0) { task_struct_offset.comm_offset = find_swapper_comm_offset((uint64_t)init_task, TASK_STRUCT_MAX_SIZE); } uint64_t stack_base = (sp & ~(thread_size - 1)); for (uintptr_t i = (uintptr_t)init_task; i < (uintptr_t)init_task + TASK_STRUCT_MAX_SIZE; i += sizeof(uintptr_t)) { uintptr_t val = *(uintptr_t *)i; if (stack_base == val) { stack_in_task_offset = i - (uintptr_t)init_task; task_struct_offset.stack_offset = stack_in_task_offset; break; } } return 0; }请问tasks_offset应该按照这样的代码方法获取呢?
03-23
给以下代码加上一个频移功能,使得signal_in到signal_out不仅有延迟还有频移 module signal_delayer ( input wire clk, input wire rst_n, input wire start, input wire [14:0] delay_cycles, input wire [15:0] signal_in, //输入发射信号 output reg [15:0] signal_out, //输出回波信号(延迟) output reg [14:0] write_ptr, output reg [14:0] read_ptr, output reg [14:0] delay_counter ); // RAM参数 - 使用15位地址,深度32768 localparam RAM_DEPTH = 32768; localparam ADDR_WIDTH = 15; // 读写指针 //reg [ADDR_WIDTH-1:0] write_ptr; //reg [ADDR_WIDTH-1:0] read_ptr; reg [ADDR_WIDTH-1:0] delay_offset; // 延迟计数器 //reg [14:0] delay_counter; reg delaying; reg data_valid; // 双端口RAM reg [9:0] delay_ram [0:RAM_DEPTH-1]; // 初始化 initial begin write_ptr = 0; read_ptr = 0; delay_counter = 0; delaying = 0; data_valid = 0; end // 计算读指针偏移量 always @(posedge clk) begin if (start) begin // 计算延迟对应的地址偏移 // 确保不超过RAM深度 if (delay_cycles < RAM_DEPTH) begin delay_offset <= delay_cycles[ADDR_WIDTH-1:0]; end else begin delay_offset <= RAM_DEPTH - 1; end delaying <= 1; //start指令发送后的初始化 data_valid <= 0; end end // 写指针逻辑 - 持续循环写入 always @(posedge clk) begin if (!rst_n) begin write_ptr <= 0; end else begin write_ptr <= write_ptr 1; // 写入RAM delay_ram[write_ptr] <= signal_in; end end // 读指针逻辑 always @(posedge clk) begin if (!rst_n) begin read_ptr <= 0; signal_out <= 0; data_valid <= 0; delay_counter <= 0; end else if (delaying) begin //start信号下发后启动delaying if (delay_counter < delay_cycles-1) begin // 延迟计数 delay_counter <= delay_counter 1; signal_out <= 0; data_valid <= 0; end else begin if (write_ptr >= delay_offset) begin read_ptr <= write_ptr - delay_offset; end else begin
09-26
请重新将以下代码按照代码规范进行缩进,然后输出一遍: import socket import struct import argparse import random import string import time import threading from collections import defaultdict " python mdns_responder.py --iface_ip 192.168.0.100 " MDNS_ADDR = “224.0.0.251” MDNS_PORT = 5353 class DNSError(Exception): “”“DNS错误基类”“” pass def generate_random_service_id(length=8): “”“生成8位随机服务ID(大写字母+数字)”“” return ‘’.join(random.choices(string.ascii_uppercase + string.digits, k=length)) def generate_random_hostname_suffix(length=8): “”“生成随机主机名后缀(数字)”“” return ‘’.join(random.choices(string.digits, k=length)) def parse_dns_name(data: bytes, offset: int) -> tuple: “”" 解析DNS名称(支持压缩指针) 返回: (域名, 新偏移量) “”" labels = [] traversed = set() while offset < len(data): length = data[offset] offset += 1 if length == 0: # 结束标记 break # 处理压缩指针 if length & 0xC0 == 0xC0: if offset >= len(data): raise DNSError("压缩指针不完整") ptr_offset = ((length & 0x3F) << 8) | data[offset] offset += 1 if ptr_offset in traversed: break traversed.add(ptr_offset) if ptr_offset >= len(data): break name_part, _ = parse_dns_name(data, ptr_offset) labels.append(name_part) break # 处理普通标签 end = offset + length if end > len(data): break labels.append(data[offset:end].decode('utf-8', 'ignore')) offset = end return '.'.join(labels), offset def build_dns_name(name: str, compress_dict: dict, base_offset: int) -> bytes: “”" 构建DNS名称(支持压缩) compress_dict: {域名: 偏移量} base_offset: 当前数据起始偏移 “”" encoded = b’’ parts = name.split(‘.’) for i in range(len(parts)): partial = '.'.join(parts[i:]) # 应用压缩 if len(partial) > 3 and partial in compress_dict: ptr = compress_dict[partial] if ptr < 0x4000: encoded += struct.pack('!H', 0xC000 | ptr) return encoded # 添加标签 label = parts[i] if not 1 <= len(label) <= 63: raise DNSError(f"无效标签长度: {len(label)}") encoded += bytes([len(label)]) + label.encode('utf-8') # 注册压缩点 current = '.'.join(parts[i:]) pos = base_offset + len(encoded) - len(label) - 1 if len(current) > 3 and current not in compress_dict: compress_dict[current] = pos encoded += b'\x00' return encoded def create_service_response(transaction_id: int, service_type: str, instance_name: str, host_name: str, ip: str, port: int) -> bytes: “”" 创建单服务响应包 “”" compress_dict = {} parts = [] current_offset = 12 # DNS头部长12字节 # === DNS头部 === flags = 0x8400 # QR=1, AA=1 qdcount = 0 # 无查询部分 ancount = 3 # PTR + SRV + A header = struct.pack("!HHHHHH", transaction_id, flags, qdcount, ancount, 0, 0) parts.append(header) # === PTR记录 === ptr_name = build_dns_name(service_type, compress_dict, current_offset) ptr_data = build_dns_name(instance_name, compress_dict, current_offset + len(ptr_name) + 10) ptr_record = ( ptr_name + struct.pack("!HHIH", 12, 1, 4500, len(ptr_data)) + # TYPE=PTR, CLASS=IN, TTL=120 ptr_data ) parts.append(ptr_record) current_offset += len(ptr_record) # === SRV记录 === srv_name = build_dns_name(instance_name, compress_dict, current_offset) srv_data = struct.pack("!HHH", 0, 0, port) # 优先级, 权重, 端口 srv_data += build_dns_name(host_name, compress_dict, current_offset + len(srv_name) + 10 + len(srv_data)) srv_record = ( srv_name + struct.pack("!HHIH", 33, 1, 120, len(srv_data)) + # TYPE=SRV srv_data ) parts.append(srv_record) current_offset += len(srv_record) # === A记录 === a_name = build_dns_name(host_name, compress_dict, current_offset) a_data = socket.inet_aton(ip) a_record = ( a_name + struct.pack("!HHIH", 1, 1, 120, 4) + # TYPE=A a_data ) parts.append(a_record) return b''.join(parts) def create_pair_response(transaction_id: int, airplay_instance: str, raop_instance: str, host_name: str, ip: str) -> bytes: “”" 创建服务对响应包(AirPlay + RAOP) “”" compress_dict = {} parts = [] current_offset = 12 # === DNS头部 === flags = 0x8400 qdcount = 0 ancount = 5 # 2 PTR + 2 SRV + 1 A header = struct.pack("!HHHHHH", transaction_id, flags, qdcount, ancount, 0, 0) parts.append(header) # === AirPlay PTR === ptr_ap_name = build_dns_name("_airplay._tcp.local", compress_dict, current_offset) ptr_ap_data = build_dns_name(airplay_instance, compress_dict, current_offset + len(ptr_ap_name) + 10) ptr_ap_record = ptr_ap_name + struct.pack("!HHIH", 12, 1, 120, len(ptr_ap_data)) + ptr_ap_data parts.append(ptr_ap_record) current_offset += len(ptr_ap_record) # === AirPlay SRV === srv_ap_name = build_dns_name(airplay_instance, compress_dict, current_offset) srv_ap_data = struct.pack("!HHH", 0, 0, 5000) srv_ap_data += build_dns_name(host_name, compress_dict, current_offset + len(srv_ap_name) + 10 + len(srv_ap_data)) srv_ap_record = srv_ap_name + struct.pack("!HHIH", 33, 1, 120, len(srv_ap_data)) + srv_ap_data parts.append(srv_ap_record) current_offset += len(srv_ap_record) # === RAOP PTR === ptr_raop_name = build_dns_name("_raop._tcp.local", compress_dict, current_offset) ptr_raop_data = build_dns_name(raop_instance, compress_dict, current_offset + len(ptr_raop_name) + 10) ptr_raop_record = ptr_raop_name + struct.pack("!HHIH", 12, 1, 120, len(ptr_raop_data)) + ptr_raop_data parts.append(ptr_raop_record) current_offset += len(ptr_raop_record) # === RAOP SRV === srv_raop_name = build_dns_name(raop_instance, compress_dict, current_offset) srv_raop_data = struct.pack("!HHH", 0, 0, 7000) srv_raop_data += build_dns_name(host_name, compress_dict, current_offset + len(srv_raop_name) + 10 + len(srv_raop_data)) srv_raop_record = srv_raop_name + struct.pack("!HHIH", 33, 1, 120, len(srv_raop_data)) + srv_raop_data parts.append(srv_raop_record) current_offset += len(srv_raop_record) # === 共享A记录 === a_name = build_dns_name(host_name, compress_dict, current_offset) a_data = socket.inet_aton(ip) a_record = a_name + struct.pack("!HHIH", 1, 1, 120, 4) + a_data parts.append(a_record) return b''.join(parts) class MDNSResponder: def init(self, iface_ip: str): “”“mDNS响应器初始化”“” self.iface_ip = iface_ip self.services = [] # 所有服务对 self.service_map = defaultdict(list) # 服务类型到实例的映射 self.running = False # 创建socket self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 多播设置 self.sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255) self.sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(iface_ip)) try: self.sock.bind(("", MDNS_PORT)) mreq = struct.pack("!4s4s", socket.inet_aton(MDNS_ADDR), socket.inet_aton(iface_ip)) self.sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) print(f"[mDNS] Socket bound to {MDNS_ADDR}:{MDNS_PORT}") except Exception as e: raise RuntimeError(f"Socket初始化失败: {e}") def generate_services(self, start_ip: str, count: int): """生成服务对(每对包含AirPlay和RAOP服务)""" base_ip, start_num = start_ip.rsplit('.', 1) start_num = int(start_num) for i in range(count): # 生成递增IP地址 ip = f"{base_ip}.{start_num + i}" # 生成唯一服务ID(8位字符) service_id = generate_random_service_id() # 生成主机名(主机名后缀为8位数字) host_suffix = generate_random_hostname_suffix() host_name = f"host-{host_suffix}.local" # AirPlay实例名 airplay_instance = f"{service_id}._airplay._tcp.local" # RAOP实例名(遵循Apple规范) raop_instance = f"{service_id}@AirPlay._raop._tcp.local" # 添加到服务列表 self.services.append({ "ip": ip, "host_name": host_name, "airplay_instance": airplay_instance, "raop_instance": raop_instance }) # 添加到服务映射 self.service_map["_airplay._tcp.local"].append( (airplay_instance, host_name, ip, 5000) ) self.service_map["_raop._tcp.local"].append( (raop_instance, host_name, ip, 7000) ) print(f"[生成服务] 已创建 {count} 对服务") def start(self): """启动mDNS响应器""" self.running = True print(f"[mDNS响应器] 在 {self.iface_ip} 上启动") while self.running: try: data, addr = self.sock.recvfrom(2048) if len(data) < 12: continue # 处理数据包 self.handle_packet(data, addr) except Exception as e: if self.running: # 防止关闭时的报错 print(f"处理报文错误: {e}") def handle_packet(self, data: bytes, addr: tuple): """处理接收到的mDNS查询(支持多问题查询)""" # 解析头部 transaction_id = struct.unpack("!H", data[0:2])[0] flags = struct.unpack("!H", data[2:4])[0] qdcount = struct.unpack("!H", data[4:6])[0] # 问题数量 # 只处理查询请求 if flags & 0x8000: return offset = 12 # DNS头部后开始解析问题 services_to_respond = set() # 收集需要响应的服务类型 # 循环读取所有问题 for _ in range(qdcount): try: # 解析域名 qname, new_offset = parse_dns_name(data, offset) # 读取类型和类(各2字节) if new_offset + 4 > len(data): break qtype, qclass = struct.unpack("!HH", data[new_offset:new_offset+4]) offset = new_offset + 4 # 只处理PTR查询(qtype=12)且类为IN(qclass=1) if qtype != 12 or qclass != 1: continue service_type = qname.rstrip('.').lower() if service_type in self.service_map: services_to_respond.add(service_type) except DNSError as e: # 跳过当前问题,继续下一个 continue # 对每个需要响应的服务类型,发送响应 for service_type in services_to_respond: print(f"[查询] 来自 {addr[0]} 查询 {service_type}") for instance_info in self.service_map[service_type]: instance_name, host_name, ip, port = instance_info try: response = create_service_response( transaction_id, service_type, instance_name, host_name, ip, port ) self.sock.sendto(response, (MDNS_ADDR, MDNS_PORT)) except Exception as e: print(f"构建响应错误: {e}") def stop(self): """停止响应器""" self.running = False self.sock.close() print("[mDNS响应器] 已停止") class ServiceAnnouncer: def init(self, iface_ip: str, services: list): “”“服务广播器初始化”“” self.iface_ip = iface_ip self.services = services self.running = False # 创建广播socket self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self.sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255) self.sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(iface_ip)) def start(self): """启动服务广播""" self.running = True print("[广播器] 开始周期性广播服务") broadcast_count = 0 while self.running: try: broadcast_count += 1 broadcast_time = time.strftime("%Y-%m-%d %H:%M:%S") print(f"\n[广播 #{broadcast_count}] 开始于 {broadcast_time}") # 广播每个服务对 for idx, service in enumerate(self.services): transaction_id = random.randint(0, 0xFFFF) try: response = create_pair_response( transaction_id, service["airplay_instance"], service["raop_instance"], service["host_name"], service["ip"] ) self.sock.sendto(response, (MDNS_ADDR, MDNS_PORT)) print(f" 已广播服务对 #{idx+1}/{len(self.services)}: {service['ip']}") except Exception as e: print(f" 广播错误: {e}") # 等待下次广播 sleep_interval = 120 # 2分钟 for _ in range(sleep_interval): if not self.running: break time.sleep(1) except Exception as e: print(f"广播错误: {e}") def stop(self): """停止广播""" self.running = False self.sock.close() print("[广播器] 已停止") def main(): parser = argparse.ArgumentParser(description=“AirPlay & RAOP mDNS 批量响应器”) parser.add_argument(“–iface_ip”, required=True, help=“网络接口IP”) parser.add_argument(“–start_ip”, default=“192.168.0.2”, help=“起始IP地址 (默认: 192.168.0.2)”) parser.add_argument(“–count”, type=int, default=100, help=“服务对数量 (默认: 100)”) args = parser.parse_args() # 创建响应器 responder = MDNSResponder(args.iface_ip) # 生成服务 responder.generate_services(args.start_ip, args.count) # 启动响应线程 responder_thread = threading.Thread(target=responder.start, daemon=True) responder_thread.start() print("服务已启动,按Ctrl+C退出...") try: # 主线程等待中断信号 while True: time.sleep(1) except KeyboardInterrupt: print("正在停止...") # 设置停止标志(如果类中有) responder.running = False # 也可以调用stop方法,但注意线程可能阻塞在recvfrom或sleep中 # 所以设置标志后,还需要中断这些阻塞(例如关闭socket) responder.stop() # 等待线程结束(如果有必要) responder_thread.join(timeout=1.0) print("已退出") if name == “main”: main()
最新发布
10-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值