与程序交互的问题
前言
这个问题是在做逆向时碰到的,就是一个猜数字的游戏,要猜对一百轮,这时,我的第一个想法是写一个自动与程序交互的脚本,于是就开始网上找有没有类似的脚本或方法了。
首先,要说明的是我并没有做出来关于这个猜数字程序的自动交互脚本,因为在这过程中遇到了个问题,这在下面讲述,所以我的方法只是面向一个简单的test程序:
1 |
|
其次,我只是对我的方法进行一个叙述,说实话,这个方法很臭,我是真的想不出来好的方法了T_T T_T T_T
问题
使用python的subprocess模块,
如果将程序输入输出导入subprocess模块的PIPE,即:
p = subprocess.Popen("test_fflush.exe", stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True, bufsize=0)
之后读取程序输出时使用readline()
会堵塞程序的进行。
如果将程序的输出导入标准输出,然后使用终端运行该脚本,即:
p = subprocess.Popen("test_fflush.exe", stdin=subprocess.PIPE, stdout=sys.stdout, shell=True, bufsize=0)
标准输出直接返回到终端上了,我看到但无法在程序中获取。
如果将程序的输出导入到文件中,同时写入文件时的缓冲区也为0,即:
with open('file.txt', 'wb+', buffering=0) as f:
p = subprocess.Popen("test_fflush.exe", stdin=subprocess.PIPE, stdout=f, shell=True, bufsize=0)
(以下其实并不完全确定是否正确)如果程序具有缓冲区,那程序的输出也无法直接实时地推到文件中,我就无法在程序中读取文件获取程序输出了。在这种情况下,如果程序的缓冲区为0,即每次输出后有fflush()
的话,就可以通过执行system命令读取文件内容实时获取输出。
简而言之就是,单纯交互的方法做不出来。
思路
本来想叫这部分内容为解决方法的,但这其实并不能称之为解决方法,毕竟要解决的是与自己写的一个简单的test程序进行交互。
所以,现在碰到的问题是什么?是无法在脚本执行过程中获取程序的输出。
在第三种情况:把输出导入到文件中,因为程序的输出在缓冲区没有刷新,文件里没有内容,所以获取不了输出。
正道走不了就走偏一点。
因此,想到的第一个方法DLL注入:让程序执行一次setvbuf()
,使缓冲区为0。
好消息:注入成功了;坏消息:没用。
按理来说是可以的,但我并不清楚为啥不成功。
然后,想到的第二个方法是IAT hook:每次程序执行完一次输出,就执行fflush()
,刷新缓冲区。
这里要说明的是,我现在要解决的是我的test程序,里面的输出都是由printf()
来完成的,所以我清楚我需要直接hook printf()
函数,这其实也是这个思路的一个局限,我不一定知道程序的输出采用哪一个输出函数。
结果同样不行。
最后,想到的第三个方法是,既然我都实现了IAT hook了,那我直接在我自己写的printf()
中获取printf()
的参数,然后直接将其写入一个文件中,这样我的脚本就可以读取文件的内容获取每一次输出的内容了。
结果是这个方法成功了,但麻烦无比。
代码
自己的printf()
函数
重写了的printf()
函数其实并不美丽,我只是简单写了一下。
实际上的printf()
函数使用的是可变参数来获取其后面的参数,然后根据第一个参数格式字符串来解析后面变量的类型。
这里,我采用同样的思路,只是解析写得简单了很多,然后使用可变参数获取后面的参数。
1 | int MyPrintf(const char* formatOri, ...) |
交互脚本
1 | import os |