先上示例代码
#define _CRT_SECURE_NO_DEPRECATE #include<stdio.h> #include<string.h> #include<stdlib.h> const char PASSWORD[] = "15pb"; int main() { int nFlag = 0; char szBuffer[8] = { 0 }; char szPassWord[12] = { 0 }; while (true) { printf("Please input password:"); scanf("%s", szPassWord); nFlag = strcmp(PASSWORD, szPassWord); strcpy(szBuffer, szPassWord); if (!nFlag) { printf("Hello 15pb(Flag = %d)\n", nFlag); system("pause"); } } return 0; }
该代码正确的密码是 “15pb”,若输入成功,会输出 "Hello 15pb(Flag = 0)" ,否则需要重新输入
首先随意输入一个错误密码1234567890,单步调试,观察内存,可以看到字符数组 szPassWord 和 szBuffer,以及标识符 nFlag 的存储位置。
其中 szPassWord 占用12个字节,szBuffer 占用8个字节,但使用 strcpy 函数之后将 szPassWord 数组里的11个字节复制到 szBuffer 里,造成栈溢出。若输入的密码足够长,最终将 nFlag 的第一个字节修改为 00,则也会输出 "Hello 15pb(Flag = 0)" ,达到目的。
但要注意的是,根据 strcmp 函数,输入的密码的 ASCLL 码值要小于 "15pb",这样 nFlag 值是1,只要输入16个字符,其最后的字符串结束符0就能修改1为0
输入密码1515151515151515,查看内存, 发现 nFlag 被修改为0,能够输出
若输入密码1616161616161616,
其
ASCLL 码值大于原密码的
ASCLL 码,nFlag 为-1,在内存中是 ff ff ff ff,复制之后0修改第一位 ff 后变为 00 ff ff ff,就无法输出
|
|
---|---|
|
如果是栈溢出的话,需要楼主证明能通过漏洞直接得到shell,但是楼主好像没做下去啊。。。 |
|
pureGavin 如果是栈溢出的话,需要楼主证明能通过漏洞直接得到shell,但是楼主好像没做下去啊。。。 初学软件安全,只能做到这一步 |
|
jieSh 初学软件安全,只能做到这一步 Explanation: 6a 0b push 0xb 58 pop eax 99 cdq 68 2f 73 68 00 push 0x68732f 68 2f 62 69 6e push 0x6e69622f 89 e3 mov ebx,esp 31 c9 xor ecx,ecx cd 80 int 0x80 这是我在用的shellcode,目前是我能找到的最短的版本了(大神勿喷),楼主可以拿去学习 |
|
pureGavin Explanation: 6a 0b &a ... 谢谢大佬 |
|
jieSh 谢谢大佬 有不懂的就问我,我尽量帮你 |
返回