0%

Android WebStite

安卓网络操作

以前就想写安卓的网络操作,方便在手机上进行渗透测试和挂机,这次就好好分析一下这个东西,也是和Windows下面一样,主要就是Get和POST这两种网页操作,POST的话呢还分为普通表单和文件上传表单,再就是有个json的对象。

GET请求

这个相对是最简单得了,也就是流之间的操作。
布局什么的我就不写了
首先我们还是要进行权限的分配:

1
2
<uses-permission 
android:name="android.permission.INTERNET"/>

就是常用的这个Internet权限
因为我们不能在主线程中对网络进行操作,所以我们最方便的就是在AsyncTask中进行效应的操作,重写他的doInBackground的方法。
首先我们先获取对应的URL对象,通过URL对象获取HttpURLConnection对象。

1
2
URL url = new URL(params[0]);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();

获取完毕这个对象之后,我们来设置一下访问的基本配置,也就是超时的设置:

1
2
3
connection.setConnectTimeout(5000);//连接超时
connection.setReadTimeout(5000);//read读取异常
connection.setDoInput(true);

第一个是连接超级,第二个是读文件超时,设置之后如果超时,会抛异常的,第三个可设置也可不设置,默认就是true,可以获取返回内容。

1
//connection.connect();

这个可以写也可以不写,这个连接其实也就是那个setConnectTimeout所说的那个连接,如果不写的话呢也可以,在getResponseCode这个方法调用的时候会判断是否有连接。,没有的话呢也就会连接的。
设置连接的请求方式:

1
connection.setRequestMethod("GET");

获取相应的状态码:

1
int code = connection.getResponseCode();

这一步会判断是否有链接并帮助连接,返回的就是HTTP的状态码,获取完毕之后,我们就可以获取响应头部:getHeaderFields().toString()这个就可以获取完整的响应头。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
if(code == 200)
{
Log.d("wker", connection.getHeaderFields().toString());
String[] type = connection.getContentType().split("=");
String encodeing="";
if(type.length>1)
encodeing = type[1];
if(encodeing=="")
encodeing="utf-8";
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(),encodeing));
char [] ReText = new char[1024];
int len = 0;

while((len=br.read(ReText))!=-1)
{
result+=new String(ReText,0,len);
}
br.close();
}

首先我们先判断响应的状态码是否是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
2
3
OutputStream os = connection.getOutputStream();
os.write("n=fanke&p=fanke".getBytes("UTF-8"));
os.close();

流的操作也是比较简单,根据编码将我们的数据写入就好了。

Cookie插入

1
connection.setRequestProperty("Cookie", "x=fanke");//带Cookie

这个其实也就是在我们的协议头带上去就好。

其他的都和GET类似。

文件提交

这个是相对而言比较难的,和前两个一样,我们先要获取链接对象:

1
2
3
4
URL url = new URL("http://192.168.209.1/upload-labs-master/Pass-01/index.php?action=show_code");
HttpURLConnection huc = (HttpURLConnection) url.openConnection();
huc.setDoOutput(true);
huc.setRequestMethod("POST");

在基本上和POST是一样的。
下面开始有区别了:

1
huc.setRequestProperty("Content-Type", "multipart/form-data; boundary="+boundary);

这个就是设置是文件的提交,比较关键的是boundary这个东西,一般是个时间戳比较好,但是不是恨死,可以自己设置,但是在下面提交的时候要多加个“–”,这是个坑。

1
2
3
4
5
6
StringBuilder sb = new StringBuilder();
sb.append("--"+boundary+rn);
sb.append("Content-Disposition: form-data; name=\"upload_file\"; filename=\"1.jpg\""+rn);
sb.append("Content-Type: image/jpeg"+rn+rn);
OutputStream opt = huc.getOutputStream();
opt.write(sb.toString().getBytes());

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void writeFile(OutputStream opt)
{
try {
FileInputStream input = new FileInputStream("/data/1.jpg");
int len = 0;
byte[] buffer = new byte[1024];
while((len=input.read(buffer))!=-1)
{
opt.write(buffer,0,len);
}
input.close();
} catch (Exception e) {
e.printStackTrace();
}
}

这个就比较常规了,就是一个文件的写入操作,我们用来将我们的文件写入我们的网络传输流中:
writeFile(opt);

我们将图片写入流中之后,写我们的结尾,下面这块有变动,是根据抓到包进行分析:

1
2
3
4
opt.write((rn+"--"+boundary+rn).getBytes());
opt.write(("Content-Disposition: form-data; name=\"submit\""+rn+rn).getBytes());
opt.write((URLEncoder.encode("上传", "utf-8")+rn+"--"+boundary).getBytes());
opt.close();

因为文件内容和boundary有分隔,所以不要忘记rn和–,下面的是抓包抓到的,记得注意的是,编码和“rn+”–”+boundary”,最后将我们的流关掉。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int code = huc.getResponseCode();
if(code==200)
{
Log.d("wker", "上传成功");
Log.d("wker", huc.getHeaderFields().toString());
String[] type = huc.getContentType().split("=");
String encodeing="";
if(type.length>1)
encodeing = type[1];
if(encodeing=="")
encodeing="utf-8";
BufferedReader br = new BufferedReader(new InputStreamReader(huc.getInputStream(),encodeing));
char [] ReText = new char[1024];
int len = 0;
String result = null;
while((len=br.read(ReText))!=-1)
{
result+=new String(ReText,0,len);
}
return result;
}else
{
Log.d("wker", "上传失败");
}

这段代码就没有什么区别了。

JSON数据的解析

这个操作起来不是很难,java提供给我们很好地一个类。
JSONArraygetJSONObject这两个类,可以嵌套使用参数都是字符串,都是传进来要解析的json数据,第一个是数组,第二个是对象。
示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Override
protected void onPostExecute(String result)
{
StringBuilder sb = new StringBuilder();
try {
JSONArray ja = new JSONArray(result);

for(int i=0;i<ja.length();i++){
JSONObject jsonObject = ja.getJSONObject(i);
String time = jsonObject.getString("onlinetime");
String number = jsonObject.getString("onlinenumber");
String change = jsonObject.getString("onlinechange");
sb.append("时间:"+time+"数值:"+number+"波动值:"+change+rn);
}
} catch (JSONException e) {
e.printStackTrace();
}
ResultText.setText(sb.toString());
};

使用起来也就是这样,但是要抛出一个异常出来
这个就是下先获取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的解析,上面的代码就是,最后运行的结果:
示例结果