安卓网络操作
以前就想写安卓的网络操作,方便在手机上进行渗透测试和挂机,这次就好好分析一下这个东西,也是和Windows下面一样,主要就是Get和POST这两种网页操作,POST的话呢还分为普通表单和文件上传表单,再就是有个json的对象。
GET请求
这个相对是最简单得了,也就是流之间的操作。
布局什么的我就不写了
首先我们还是要进行权限的分配:
1 | <uses-permission |
就是常用的这个Internet权限
因为我们不能在主线程中对网络进行操作,所以我们最方便的就是在AsyncTask
中进行效应的操作,重写他的doInBackground
的方法。
首先我们先获取对应的URL对象,通过URL对象获取HttpURLConnection
对象。
1 | URL url = new URL(params[0]); |
获取完毕这个对象之后,我们来设置一下访问的基本配置,也就是超时的设置:
1 | connection.setConnectTimeout(5000);//连接超时 |
第一个是连接超级,第二个是读文件超时,设置之后如果超时,会抛异常的,第三个可设置也可不设置,默认就是true,可以获取返回内容。
1 | //connection.connect(); |
这个可以写也可以不写,这个连接其实也就是那个setConnectTimeout
所说的那个连接,如果不写的话呢也可以,在getResponseCode
这个方法调用的时候会判断是否有连接。,没有的话呢也就会连接的。
设置连接的请求方式:
1 | connection.setRequestMethod("GET"); |
获取相应的状态码:
1 | int code = connection.getResponseCode(); |
这一步会判断是否有链接并帮助连接,返回的就是HTTP的状态码,获取完毕之后,我们就可以获取响应头部:getHeaderFields().toString()
这个就可以获取完整的响应头。
1 | if(code == 200) |
首先我们先判断响应的状态码是否是200,如果是的话呢,我们就先分解编码方式,判断是什么,如果没有的话呢,我们默认设置为UTF-8的编码方式,然后我们获取字符的输入流,通过连接对象的getInputStream
方法就可以获取,并且我们需要指定我们的编码方式,之后的读取就是常规的流读取了,最后将这个流关闭。
POST请求
这个能稍微麻烦那么一点,先说一下常规的普通表单的提交方式:
普通表单
和GET方式相似,不同的地方,我写出来
1 | connection.setRequestMethod("POST"); |
我们设置为POST提交方式。
1 | connection.setDoOutput(true); |
这个代表有输出,也就是POST表单内容要进行输出(也就是在协议头下面有内容)
1 | connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); |
这个就很关键了,这个代表是POST的提交数据,设置好之后,我们饿要获取输出流:
1 | OutputStream os = connection.getOutputStream(); |
流的操作也是比较简单,根据编码将我们的数据写入就好了。
Cookie插入
1 | connection.setRequestProperty("Cookie", "x=fanke");//带Cookie |
这个其实也就是在我们的协议头带上去就好。
其他的都和GET类似。
文件提交
这个是相对而言比较难的,和前两个一样,我们先要获取链接对象:
1 | URL url = new URL("http://192.168.209.1/upload-labs-master/Pass-01/index.php?action=show_code"); |
在基本上和POST是一样的。
下面开始有区别了:
1 | huc.setRequestProperty("Content-Type", "multipart/form-data; boundary="+boundary); |
这个就是设置是文件的提交,比较关键的是boundary这个东西,一般是个时间戳比较好,但是不是恨死,可以自己设置,但是在下面提交的时候要多加个“–”,这是个坑。
1 | StringBuilder sb = new StringBuilder(); |
rn这个变量其实就是”\r\n”,也就是一个换行,我们用一个字符串容器将它进行包含,之后我们接上:”–”+boundary+rn,这个是固定。sb.append("Content-Disposition: form-data; name=\"upload_file\"; filename=\"1.jpg\""+rn);
这个基本也是固定的,也就是这个地方容易出现文件上传的基本漏洞,抓包可以看到的,rn不要忘记带,sb.append("Content-Type: image/jpeg"+rn+rn);
这个及时设置我们是图片文件(一种上传漏洞)然后我们获取输入流。
写个方法将我们的文件内容上传上去:
1 | private void writeFile(OutputStream opt) |
这个就比较常规了,就是一个文件的写入操作,我们用来将我们的文件写入我们的网络传输流中:writeFile(opt);
我们将图片写入流中之后,写我们的结尾,下面这块有变动,是根据抓到包进行分析:
1 | opt.write((rn+"--"+boundary+rn).getBytes()); |
因为文件内容和boundary有分隔,所以不要忘记rn和–,下面的是抓包抓到的,记得注意的是,编码和“rn+”–”+boundary”,最后将我们的流关掉。
1 | int code = huc.getResponseCode(); |
这段代码就没有什么区别了。
JSON数据的解析
这个操作起来不是很难,java提供给我们很好地一个类。JSONArray
和getJSONObject
这两个类,可以嵌套使用参数都是字符串,都是传进来要解析的json数据,第一个是数组,第二个是对象。
示例代码:
1 |
|
使用起来也就是这样,但是要抛出一个异常出来
这个就是下先获取JSON数组,然后解析数组里面的成员因为是对象类型,所以再嵌套为对象,然后通过键值进行获取。
实例
就是通过API接口分析,然后提交数据,奇趣那个网站:
http://77tj.org/api/tencent/onlineim
返回的json对象:
1 | [{"onlinetime":"2020-03-07 10:24:00","onlinenumber":323597394,"onlinechange":33184},{"onlinetime":"2020-03-07 10:23:00","onlinenumber":323564210,"onlinechange":55485},{"onlinetime":"2020-03-07 10:22:00","onlinenumber":323508725,"onlinechange":60889},{"onlinetime":"2020-03-07 10:21:00","onlinenumber":323447836,"onlinechange":115561},{"onlinetime":"2020-03-07 10:20:00","onlinenumber":323332275,"onlinechange":17549},{"onlinetime":"2020-03-07 10:19:00","onlinenumber":323314726,"onlinechange":54134},{"onlinetime":"2020-03-07 10:18:00","onlinenumber":323260592,"onlinechange":2632},{"onlinetime":"2020-03-07 10:17:00","onlinenumber":323257960,"onlinechange":156081},{"onlinetime":"2020-03-07 10:16:00","onlinenumber":323101879,"onlinechange":-7806},{"onlinetime":"2020-03-07 10:15:00","onlinenumber":323109685,"onlinechange":81895}] |
我们解析也就是先传入GET,然后在UI中进行JSON的解析,上面的代码就是,最后运行的结果: