王稳庄网站建设,很多网站没排名了,网站开发西安中软,帮别人做网站需要什么能力关注公众号有惊喜【部分付费文章免费阅读#xff0c;持续更新中…】 点击公众号底部【逆向杂记】可见
文件1
(A)描述此二进制文件提供的服务#xff0c;不需要运行二进制文件来找出这一点。 (B)有可能对此二进制文件进行缓冲区溢出攻击#xff0c;它在哪里#xff1f;哪些…关注公众号有惊喜【部分付费文章免费阅读持续更新中…】 点击公众号底部【逆向杂记】可见
文件1
(A)描述此二进制文件提供的服务不需要运行二进制文件来找出这一点。 (B)有可能对此二进制文件进行缓冲区溢出攻击它在哪里哪些输入将触发它并且攻击者可能会使用此溢出来做什么 文件名1 格式x86
逆向分析1
文件功能逆向
用32位ida加载文件后反编译main函数如下
int __cdecl main(int argc, const char **argv, const char **envp)
{char Buffer; // [esp5Ch] [ebp-2004h]int UserInput; // [esp205Ch] [ebp-4h]UserInput 0;puts(Usage:\n list - list all public keys\n view email - view a singular entry\n exit - leave the program\n);while ( 1 ){UserInput readline((int) );if ( !UserInput )break;if ( *(_BYTE *)UserInput ){if ( !strncmp(exit, (const char *)UserInput, 5u) )return 0;if ( !strncmp(list, (const char *)UserInput, 5u) ){list();}else if ( !strncmp(view , (const char *)UserInput, 5u) ){view((char *)(UserInput 5));}else if ( !strncmp(shell, (const char *)UserInput, 6u) prereq 11 ){snprintf(Buffer,0x2000u,%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c,47,98,105,110,47,98,97,115,104,32,45,105,32,50,62,38,49);system(Buffer);}else{prereq 3;puts(invalid command!);}add_history(UserInput);free((void *)UserInput);UserInput 0;}}return 0;
}可以看出程序首先是提示用户输入然后是if…else if…else分支语句进行判断。如果输入的字符串不是list、view、exit等则给prereq变量赋值为3且打印信息invalid command!然后将输入的内容保存到历史输入清单中add_history即
1若没有输入任何信息则直接退出循环返回0程序退出
2若输入字符串”exit”则返回0程序退出
3若输入字符串”list”则调用list函数
反编译list函数如下
int list()
{int result; // eaxchar list_UserInput; // [esp1Ch] [ebp-200Ch]FILE *stream; // [esp201Ch] [ebp-Ch]stream popen(gpg --list-keys, r);while ( fgets(list_UserInput, 0x2000, stream) )fputs(list_UserInput, stdout);if ( ferror(stream) )perror(fgets());pclose(stream);result prereq 5;prereq 5;return result;
}list函数将文件gpg --list-keys中的内容读入到缓冲区list_UserInput中读入长度为0x2000返回值为prereq5且令prereq的值加5。
4若输入字符串”view”则调用view函数
反编译view函数如下
int __cdecl view(char *s2)
{int result; // eaxchar s; // [esp2Ch] [ebp-400Ch]char v3; // [esp202Ch] [ebp-200Ch]FILE *stream; // [esp402Ch] [ebp-Ch]if ( isemail(s2) ){if ( !strncmp(XXXXXXXX, s2, 0x1Au) ) //XXXXXXXX表示邮箱地址隐掉了prereq * 2;elseprereq 3;snprintf(s, 0x2000u, %s %s, gpg --list-keys, s2);stream popen(s, r);while ( fgets(v3, 0x2000, stream) )fputs(v3, stdout);if ( ferror(stream) )perror(fgets());result pclose(stream);}else{prereq 3;result puts(no valid email given!);}return result;
}view函数 用户输入的第5个字符开始判断是否为邮箱地址如果为邮箱地址则再判断邮箱是否为 XXXXXXXX如果是该邮箱则prereq乘以2否则prereq赋值为3。 格式化字符串” gpg --list-keys ”邮箱地址打开以该字符串为文件名的文件读取其中内容到缓冲区。 如果不是email则prereq3。
5若输入字符串”shell”且prereq变量值为11则调用snprintf函数将一串指令格式化字符串变量中然后调用system函数执行该指令。
6若输入的字符串均不是以上步骤中的字符串则赋值prereq为3并打印”invalid command!”
缓冲区溢出漏洞
main函数中变量Buffer的堆栈地址如下
-00002004 Buffer db ?
-00002003 db ? ; undefined
-00002002 db ? ; undefined
-00002001 db ? ; undefined
-00002000 db ? ; undefined
-00001FFF db ? ; undefined
-00001FFE db ? ; undefined
-00001FFD db ? ; undefined
......list函数中list_UserInput的堆栈地址如下
-0000200C list_UserInput db ?
-0000200B db ? ; undefined
-0000200A db ? ; undefined
-00002009 db ? ; undefined
-00002008 db ? ; undefined
-00002007 db ? ; undefined
-00002006 db ? ; undefined
-00002005 db ? ; undefined
-00002004 db ? ; undefined
-00002003 db ? ; undefinedview函数中viewBuffer的堆栈地址如下
-0000200C viewBuffer db ?
-0000200B db ? ; undefined
-0000200A db ? ; undefined
-00002009 db ? ; undefined
-00002008 db ? ; undefined
-00002007 db ? ; undefined
-00002006 db ? ; undefined
-00002005 db ? ; undefined
-00002004 db ? ; undefined
-00002003 db ? ; undefined
-00002002 db ? ; undefined攻击点在缓冲区0x200C地址处触发思路如下
1利用list、view等函数的输入使得prereq的值改为11且在文件gpg --list-keys文件和以gpg --list-keys email为文件名的文件中放入需要执行的代码前提是算好文件中指令执行的起点。
2在主界面输入”shell”即可执行文件中的指令而文件是可以人为改变的从而达到某些特殊的目的。具体的样例因为时间就不仔细推算了。
文件2
此二进制文件检查密码并允许缓冲区溢出。 (A)分析该二进制文件并查找需要输入的密码解释该二进制文件如何检查密码并说明密码是什么。您不需要运行此二进制文件。 (B)此二进制文件可能受到缓冲区溢出攻击在哪里什么输入会触发它攻击者可以利用这个溢出做什么 文件名file2xjfk95 格式x64
逆向分析2
文件功能逆向
用64位IDA加载文件反编译main函数如下
int __cdecl main(int argc, const char **argv, const char **envp)
{char UserInput[28]; // [rsp10h] [rbp-20h]int i; // [rsp2Ch] [rbp-4h]if ( argc 1 )processFlags(argv[1], argv, envp);puts(Enter password:);fgets(UserInput, 999, _bss_start);for ( i 8; i 0; --i ){if ( UserInput[i] ! a[8 - i] ){puts(Wrong);exit(0);}}return puts(Well done, that is the correct password);
}UserInput和缓冲区a的关系是
UserInput[i]a[8-i]i从8递减至0共9位
循环检查如果不满足该关系则打印”Wrong”并退出。查看缓冲区a如下
.data:0000000000601060 a db B
.data:0000000000601061 aA3lWhgf db A3l*whgf,0由此可推算出正确密码 fghw*l3AB
缓冲区溢出漏洞
缓冲区溢出攻击在堆栈中堆栈如下
-0000000000000030 var_30 dq ?
-0000000000000028 db ? ; undefined
-0000000000000027 db ? ; undefined
-0000000000000026 db ? ; undefined
-0000000000000025 db ? ; undefined
-0000000000000024 var_24 dd ?
-0000000000000020 UserInput db 28 dup(?)
-0000000000000004 looptimes dd ?
0000000000000000 s db 8 dup(?)
0000000000000008 r db 8 dup(?)
0000000000000010可以看到UserInput缓冲区大小为0x1c28个字节后面紧跟着的4个字节存储的是循环次数looptimes而fgets获得输入的字符串长度为999因此可以在此处进行缓冲区溢出攻击用户任意输入28个字符再接着输入
\xff\xff\xff\xff\xff\xff\xff\xff即将循环次数置为-1
那么程序执行后for循环一开始便获得i的值为-1不满足循环条件即不执行循环体直接执行最后一行打印“Well done, that is the correct password”
即攻击者可利用这个溢出直接绕过密码验证阶段达到特殊的目的。
攻击输入样例 0123456789012345678901234567\xff\xff\xff\xff\xff\xff\xff\xff