一个条件竞争的洞,以前没有接触过。比赛完研究了wp复现下。
new_thread结构体如下
new_thread: thread_area size0x8 thread_area+0x8 size 0x8 thread_area+0x10 choice thread_area+0x14 key 0x20 thread_area+0x34 IV 0x10 ... thread_area+0x60 task_id thread_area+0x68 thread_binlist thread_area+0x88 EVP_CIPHER_CTX_new
delete中并没有uaf的问题
void delete(void) { void **__ptr; int task_id; void **local_18; void **local_10; __ptr = DAT_00302028; local_18 = DAT_00302028; local_10 = DAT_00302028; printf("Task id : "); task_id = my_read8(); if ((DAT_00302028 == (void **)0x0) || (task_id != *(int *)(DAT_00302028 + 0xc))) { while (local_18 != (void **)0x0) { if (task_id == *(int *)(local_18 + 0xc)) { local_10[0xd] = local_18[0xd]; EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)local_18[0xb]); free(*local_18); free(local_18); return; } local_10 = local_18; local_18 = (void **)local_18[0xd]; } } else { DAT_00302028 = (void **)DAT_00302028[0xd]; EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)__ptr[0xb]); free(*__ptr); /* 这里不存在uaf 00302028会存储线程链的值,在释放前会判断这个值是否为空 */ free(__ptr); } return; }
存在的问题是创建新线程执行start_routine时的条件竞争(这里产生条件竞争的原因是子线程会共享主线程的bss段,在创建子线程时sleep(2)后再更新bss段的数据)
void start_routine(uchar **ppuParm1) { int iVar1; long in_FS_OFFSET; int local_34; uchar **local_30; ulong local_28; undefined8 local_20; undefined8 local_18; undefined8 local_10; local_10 = *(undefined8 *)(in_FS_OFFSET + 0x28); local_34 = 0; local_20 = 0; local_18 = 0; local_28 = 0; local_30 = ppuParm1; puts("Prepare..."); sleep(2); memset(DAT_00302030,0,0x1010); iVar1 = EVP_CipherUpdate((EVP_CIPHER_CTX *)local_30[0xb],DAT_00302030,&local_34,*local_30, (int)local_30[1]); if (iVar1 == 0) { /* WARNING: Subroutine does not return */ pthread_exit((void *)0x0); } local_28 = local_28 + (long)local_34; iVar1 = EVP_CipherFinal_ex((EVP_CIPHER_CTX *)local_30[0xb],DAT_00302030 + local_28,&local_34); if (iVar1 == 0) { /* WARNING: Subroutine does not return */ pthread_exit((void *)0x0); } local_28 = local_28 + (long)local_34; puts("Ciphertext: "); my_printf(stdout,(long)DAT_00302030,local_28,0x10,1); /* WARNING: Subroutine does not return */ pthread_exit((void *)0x0); }
神仙东西,思路大致看懂了tql,orz
总结一下学到的改变执行流的思路吧:条件竞争并不能写任意内存,程序也没有任意地址写的漏洞,这时可以尝试找一个相对地址的调用,如果这个相对地址可控,我们就可以改变执行流了