VNZ-ROAD
NEXTVNZ
Bài này từ rất lâu rồi, nhân vụ việc Zalo bị thông báo thu hồi tên miền mình xin phép đăng lại để anh em có tham khảo
Gần đây có một người bạn nhờ tôi kiểm tra xem WeChat – một ứng dụng Android (Android App) của tàu khựa có liên hệ gì với Zalo sản phẩm có tính năng tương tự của Việt Nam, do hãng VNG sản xuất hay không. Chưa từng reverse Android App nên tôi cũng mày mò và tranh thủ học hỏi thêm. Bài viết này nhằm 2 mục đích:
Phần 1: Dịch ngược:
Để bắt đầu thì trong bài viết này tôi sử dụng 2 file apk sau cho 2 ứng dụng:
File APK chính là file thực thi của một ứng dụng Android, nó thực ra là một file đóng gói của ngôn ngữ Java mà hệ điều hành Android có thể đọc được và thực thi trong môi trường HDH Android.
Khi cài đặt 1 ứng dụng từ google play, file apk sẽ nằm trong thư mục /data/app trong máy ( bài tập cho bạn: làm sao lấy được nó ra khỏi máy ? )
Sau khi lấy được 2 file này, chúng ta cần một số công cụ để dịch ngược file apk thành file java ban đầu. Để làm việc này tôi sử dụng 2 công cụ:
Công cụ (1) giúp chuyển tập tin apk thành định dạng “jar” (Java Archive) một file đóng gói khác của java.
Tuy nhiên trong file .jar chỉ toàn là java bytescode gồm các mã
lệnh dưới dạng binary của java, rất khó để đọc vì vậy tôi đã sử dụng
tiếp chương trình (2).
Kết quả:
Mã nguồn rất tuyệt và dễ đọc hơn java bytecode gấp 10000 lần
Tuy nhiên ta còn một vấn đề nhỏ. Trong quá trình đóng gói ứng dụng,
1 số thông tin của các hàm, biến v.v... đã bị xóa khỏi ứng dụng, vì mục
đích obfuscation (làm cho khó đọc). Chính vì thế ta thấy rất nhiều các
file a,b,c,d … .java xuất hiện như trên hình.
Để đỡ rối khi đọc, tạm thời tôi di chuyển các file chưa xác định
tên tuổi này vào 1 package gọi là “unk” (nghĩa là chưa biết). Một đoạn ruby script nhỏ sẽ giúp ta làm điều này.
[Code]
`mkdir unk 2>/dev/null`
Dir.glob("**/*").select { |f| not File.dirname(f) =~ /^unk/ and File.basename(f) =~ /^[a-z]{0,3}\.java$/}.each do |f|
puts f
content = open(f).read().sub("package ", "package unk.")
open(f,"w").write(content)
`mkdir -p unk/#{File.dirname(f)} 2>/dev/null`
`mv #{f} unk/#{f}`
end
[/code]
Ngoài ra tôi cũng sử dụng thêm công cụ apktool tại https://code.google.com/p/android-apktool/
để thực hiện việc lấy các thông tin về resources của ứng dụng android.
(Apktool cũng sẽ convert các file byte code thành dạng smalli và ta cũng
có thể sử dụng để hiểu thêm về ứng dụng)
Toàn bộ quá trình trên sau khi hoàn tất tôi đã đưa kết quả lên github cho các bạn nếu thích thì tìm hiểu cùng:
( Kết quả của apktool nằm trong src/resources/* )
Phần 2: So sánh mã nguồn
Để so sánh mã nguồn 2 chương trình này, tôi sử dụng gói ứng dụng PMD: http://pmd.sourceforge.net/
Gói ứng dụng PMD có kèm theo 1 chương trình cho phép kiểm tra các
đoạn code copy & paste của các file source code trong cùng 1 thư
mục. Tôi tiến hành copy file source của Zalo và WeChat vào cùng 1 thư
mục và thực hiện:
Code:
./bin/run.sh cpd --minimum-tokens 50 --files ./src/ --language java
( cpd là công cụ “copy-paste-detector”, minimum-token xác định độ dài tối thiểu của đoạn mã cần so sánh. )
Output của chương trình ra giống như sau:
Code:
Found a 257 line (1735 tokens) duplication in the following files:
Starting at line 278 of ./src/ZaloRE/src/unk/com/zing/zalo/utils/a.java
Starting at line 545 of ./src/ZaloRE/src/unk/com/zing/zalo/e/a.java
qC = new int[] { 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47, 94, 188, 99, 198, 151, 53, 106, 212, 179, 125, 250, 239, 197, 145 };
int[] arrayOfInt1 = new int[256];
arrayOfInt1[0] = -1520213050;
arrayOfInt1[1] = -2072216328;
….
=====================================================================
Found a 177 line (1211 tokens) duplication in the following files:
Starting at line 663 of ./src/WeChat/com/tencent/qqpim/dao/SYSSmsDaoV2.java
Starting at line 585 of ./src/WeChat/com/tencent/qqpim/dao/SYSSmsDaoV1.java
...
Kông tốt lắm
vì cpd không so sánh 2 bộ mã nguồn mà chỉ có so sánh trong cùng một bộ
tuy vậy ta có thể làm được điều mình muốn bằng một thủ thuật nhỏ đó là
tìm những file giống nhau trong 2 folder khác nhau từ output của chương
trình.
Tiếp tục luyện kungfu ruby script:
Code:
zalo = wechat = found = nil
File.open(ARGV[0]).each_line do |line|
if line =~ /^=+$/
puts "#{found}#{zalo}#{wechat}\n" if (zalo and wechat)
found = zalo = wechat = nil
end
found = line if line =~ /Found/
zalo = line if line =~ /Zalo/
wechat = line if line =~ /WeChat/
end
puts "#{found}#{zalo}#{wechat}\n" if (zalo and wechat)
Sau khi chạy script trên với output phần trước thì ta thấy cpd
đã tìm ra được tổng cộng 7 tập tin sau đây có sự trùng lặp giữa mã nguồn
của Zalo và WeChat =]]]]
(Các file dưới đây các bạn có thể xem tại github mình đã up lên ở phía trên, ví dụ file đầu tiên có thể xem ở https://github.com/danghvu/ZaloRE/blob/master/src/com/facebook/android/Util.java)
Hm.. liệu Zalo có ăn cắp mã của WeChat / ngược lại ? Tôi cẩn thận
xem xét từng file và nhận thấy những đoạn code giống nhau là từ những mã
nguồn của các thư viện mở mà 2 ứng dụng này cùng sử dụng.
Lấy ví dụ, ta thử so sánh:
Đây là một đoạn xử lý khi ứng dụng muốn gửi 1 request lên ứng dụng facebook ( vì Zalo và WeChat đều có facebook integration ) nằm trong bộ Facebook-Sdk (File version nằm ở src/com/facebook/FacebookSdkVersion.java )
Một điều thú vị nữa khi đọc đoạn code này là dường như cả Zalo và WeChat đều không sử dụng giao thức HTTPS
, bởi vì cả 2 cùng sử dụng “HttpURLConnection” thay vì "HttpsURLConnection” , attacker có thể dễ dàng “sniff” các gói tin … Để khẳng định điều này chúng ta sẽ sniff packet của Zalo và WeChat để so sánh, nhưng xin hẹn lại dịp sau.
Kết luận của tôi tạm thời hiện nay qua việc kiểm tra mã nguồn thì tuy có 1 số trùng lặp trong code nhưng điều đó chưa chứng tỏ được Zalo có sử dụng mã nguổn sao chép từ WeChat.
Để khẳng định rõ hơn nữa thì cần phải tiếp tục rà soát các yếu tố trong các tính năng chính của cả 2 bên, phần bộ nhớ lúc thực thi (phần sau sẽ hướng dẫn sử dụng debugger cho android) và các phần mã bị làm rối mà jd-gui không dịch ngược lại được. ( Chẳng hạn : WeChat/src/unk/com/tencent/mm/sdk/platformtools/bg.java :1272 )
Keyboard heroes detected
Trong topic bên HVA có ghi rõ ràng:
Như vậy source của Zalo và WeChat có tổng cộng 76 dòng giống nhau (trong khi source của mỗi app có hơn 20K dòng code). Và chủ topic bên đó cũng có phân tích thử 1 đoạn giống nhau là... gọi API của Facebook
Nói chung câu chuyện vẫn chưa có gì , vì trang hvaonline cũng như các trang khác đều không cập nhật nữa. Thông tin để các bạn tham khảo về code từ rất lâu của Zalo
Nguồn tham khảo hvaonline hvaonline.net/hvaonline/posts/list/44782.hva#276069
Thu hồi tên miền Zalo , Mạng xã hội có lượng người dùng lớn nhất Việt Nam , việt hóa gần như tất cả các dịch vụ : mua sắm, thanh toán, chia sẻ.v.v. mà lại bị thu hồi tên miền
Thanh tra Sở Thông tin và Truyền thông TP.HCM vừa có văn bản yêu cầu các nhà đăng ký và quản lý tên miền tại Việt Nam dừng cung cấp 2 tên miền là Zalo.vn và Zalo.me thuộc sở hữu của công ty cổ phần VNG.
Lý do của quyết định thu hồi 2 tên miền nêu trên là do Zalo đã hoạt động mạng xã hội không phép.
Trước đó, năm 2018, Thanh tra Sở cũng đã xử phạt hành chính đối với hoạt động mạng xã hội không phép này của Zalo và công ty VNG cũng đã nộp phạt.
Tuy nhiên, đến thời điểm hiện tại, phía công ty vẫn không tiến hành xin phép mạng xã hội cho Zalo, Thanh tra Sở đã ban hành quyết định xử phạt vi phạm hành chính với công ty cổ phần VNG về hành vi thiết lập mạng xã hội Zalo nhưng không có giấy phép, đồng thời gửi văn bản cho các đơn vị liên quan đến việc đăng ký và quản lý tên miền yêu cầu ngừng cung cấp 2 tên miền Zalo.vn và Zalo.me.
Theo yêu cầu của Thanh tra Sở Thông tin truyền thông TP.HCM, các bên liên quan sẽ phải dừng cung cấp tên miền Zalo.vn và Zalo.me trước ngày 19-7.
- Giới thiệu và thảo luận phương pháp và một số công cụ reverse một Android App
- Thảo luận và so sánh WeChat và Zalo, về các mặt: mã nguồn, vấn đề bảo mật người dùng, các tính năng có thể nguy hại đến người dùng
Phần 1: Dịch ngược:
Để bắt đầu thì trong bài viết này tôi sử dụng 2 file apk sau cho 2 ứng dụng:
- WeChat: http://dl.dropbox.com/u/11027388/WeChat_4.5.apk
- Zalo : http://dl.dropbox.com/u/11027388/Zalo_1.0.8.apk
File APK chính là file thực thi của một ứng dụng Android, nó thực ra là một file đóng gói của ngôn ngữ Java mà hệ điều hành Android có thể đọc được và thực thi trong môi trường HDH Android.
Khi cài đặt 1 ứng dụng từ google play, file apk sẽ nằm trong thư mục /data/app trong máy ( bài tập cho bạn: làm sao lấy được nó ra khỏi máy ? )
Sau khi lấy được 2 file này, chúng ta cần một số công cụ để dịch ngược file apk thành file java ban đầu. Để làm việc này tôi sử dụng 2 công cụ:
- dex2jar : https://code.google.com/p/dex2jar/
- jd-gui : http://java.decompiler.free.fr/?q=jdgui
Công cụ (1) giúp chuyển tập tin apk thành định dạng “jar” (Java Archive) một file đóng gói khác của java.
Mã:
dex2jar.sh Zalo_1.0.8.apk
ls
Zalo_1.0.8.jar
Tuy nhiên trong file .jar chỉ toàn là java bytescode gồm các mã
lệnh dưới dạng binary của java, rất khó để đọc vì vậy tôi đã sử dụng
tiếp chương trình (2).
Mã:
./jd-gui
Mã nguồn rất tuyệt và dễ đọc hơn java bytecode gấp 10000 lần
Tuy nhiên ta còn một vấn đề nhỏ. Trong quá trình đóng gói ứng dụng,
1 số thông tin của các hàm, biến v.v... đã bị xóa khỏi ứng dụng, vì mục
đích obfuscation (làm cho khó đọc). Chính vì thế ta thấy rất nhiều các
file a,b,c,d … .java xuất hiện như trên hình.
Để đỡ rối khi đọc, tạm thời tôi di chuyển các file chưa xác định
tên tuổi này vào 1 package gọi là “unk” (nghĩa là chưa biết). Một đoạn ruby script nhỏ sẽ giúp ta làm điều này.
[Code]
`mkdir unk 2>/dev/null`
Dir.glob("**/*").select { |f| not File.dirname(f) =~ /^unk/ and File.basename(f) =~ /^[a-z]{0,3}\.java$/}.each do |f|
puts f
content = open(f).read().sub("package ", "package unk.")
open(f,"w").write(content)
`mkdir -p unk/#{File.dirname(f)} 2>/dev/null`
`mv #{f} unk/#{f}`
end
[/code]
Ngoài ra tôi cũng sử dụng thêm công cụ apktool tại https://code.google.com/p/android-apktool/
để thực hiện việc lấy các thông tin về resources của ứng dụng android.
(Apktool cũng sẽ convert các file byte code thành dạng smalli và ta cũng
có thể sử dụng để hiểu thêm về ứng dụng)
Toàn bộ quá trình trên sau khi hoàn tất tôi đã đưa kết quả lên github cho các bạn nếu thích thì tìm hiểu cùng:
( Kết quả của apktool nằm trong src/resources/* )
Phần 2: So sánh mã nguồn
Để so sánh mã nguồn 2 chương trình này, tôi sử dụng gói ứng dụng PMD: http://pmd.sourceforge.net/
Gói ứng dụng PMD có kèm theo 1 chương trình cho phép kiểm tra các
đoạn code copy & paste của các file source code trong cùng 1 thư
mục. Tôi tiến hành copy file source của Zalo và WeChat vào cùng 1 thư
mục và thực hiện:
Code:
./bin/run.sh cpd --minimum-tokens 50 --files ./src/ --language java
( cpd là công cụ “copy-paste-detector”, minimum-token xác định độ dài tối thiểu của đoạn mã cần so sánh. )
Output của chương trình ra giống như sau:
Code:
Found a 257 line (1735 tokens) duplication in the following files:
Starting at line 278 of ./src/ZaloRE/src/unk/com/zing/zalo/utils/a.java
Starting at line 545 of ./src/ZaloRE/src/unk/com/zing/zalo/e/a.java
qC = new int[] { 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47, 94, 188, 99, 198, 151, 53, 106, 212, 179, 125, 250, 239, 197, 145 };
int[] arrayOfInt1 = new int[256];
arrayOfInt1[0] = -1520213050;
arrayOfInt1[1] = -2072216328;
….
=====================================================================
Found a 177 line (1211 tokens) duplication in the following files:
Starting at line 663 of ./src/WeChat/com/tencent/qqpim/dao/SYSSmsDaoV2.java
Starting at line 585 of ./src/WeChat/com/tencent/qqpim/dao/SYSSmsDaoV1.java
...
Kông tốt lắm
vì cpd không so sánh 2 bộ mã nguồn mà chỉ có so sánh trong cùng một bộ
tuy vậy ta có thể làm được điều mình muốn bằng một thủ thuật nhỏ đó là
tìm những file giống nhau trong 2 folder khác nhau từ output của chương
trình.
Tiếp tục luyện kungfu ruby script:
Code:
zalo = wechat = found = nil
File.open(ARGV[0]).each_line do |line|
if line =~ /^=+$/
puts "#{found}#{zalo}#{wechat}\n" if (zalo and wechat)
found = zalo = wechat = nil
end
found = line if line =~ /Found/
zalo = line if line =~ /Zalo/
wechat = line if line =~ /WeChat/
end
puts "#{found}#{zalo}#{wechat}\n" if (zalo and wechat)
Sau khi chạy script trên với output phần trước thì ta thấy cpd
đã tìm ra được tổng cộng 7 tập tin sau đây có sự trùng lặp giữa mã nguồn
của Zalo và WeChat =]]]]
(Các file dưới đây các bạn có thể xem tại github mình đã up lên ở phía trên, ví dụ file đầu tiên có thể xem ở https://github.com/danghvu/ZaloRE/blob/master/src/com/facebook/android/Util.java)
Mã:
Found a 10 line (86 tokens) duplication in the following files:
Starting at line 131 of ./src/ZaloRE/src/com/facebook/android/Util.java
Starting at line 62 of ./src/WeChat/src/unk/com/tencent/mm/ui/facebook/a/m.java
Found a 5 line (70 tokens) duplication in the following files:
Starting at line 87 of ./src/ZaloRE/src/unk/com/a/b/e.java
Starting at line 155 of ./src/WeChat/src/unk/com/tencent/mm/sdk/platformtools/bg.java
Found a 5 line (69 tokens) duplication in the following files:
Starting at line 87 of ./src/ZaloRE/src/unk/com/a/b/e.java
Starting at line 562 of ./src/WeChat/src/unk/com/tencent/mm/platformtools/bf.java
Found a 16 line (65 tokens) duplication in the following files:
Starting at line 81 of ./src/ZaloRE/src/unk/com/zing/zalo/uicontrol/w.java
Starting at line 55 of ./src/WeChat/src/unk/com/tencent/mm/modelemoji/l.java
Found a 11 line (59 tokens) duplication in the following files:
Starting at line 21 of ./src/ZaloRE/src/me/zing/vn/gl/FilterGLSurfaceView$ConfigChooser.java
Starting at line 21 of ./src/WeChat/src/unk/com/badlogic/gdx/backends/android/w.java
Found a 13 line (59 tokens) duplication in the following files:
Starting at line 161 of ./src/ZaloRE/src/com/zing/zalo/uicontrol/HorizontalPager.java
Starting at line 148 of ./src/WeChat/src/com/tencent/mm/ui/base/MMFlipper.java
Found a 16 line (55 tokens) duplication in the following files:
Starting at line 12 of ./src/ZaloRE/src/unk/com/zing/zalo/plugin/a.java
Starting at line 36 of ./src/WeChat/src/com/android/internal/telephony/ISms$Stub.java
Hm.. liệu Zalo có ăn cắp mã của WeChat / ngược lại ? Tôi cẩn thận
xem xét từng file và nhận thấy những đoạn code giống nhau là từ những mã
nguồn của các thư viện mở mà 2 ứng dụng này cùng sử dụng.
Lấy ví dụ, ta thử so sánh:
Mã:
Starting at line 131 of ./src/ZaloRE/src/com/facebook/android/Util.java
Starting at line 62 of ./src/WeChat/src/unk/com/tencent/mm/ui/facebook/a/m.java
if (!paramBundle.containsKey("method")) "
paramBundle.putString("method", paramString2);
if (paramBundle.containsKey("access_token"))
paramBundle.putString("access_token", URLDecoder.decode(paramBundle.getString("access_token")));
localHttpURLConnection.setRequestMethod("POST");
localHttpURLConnection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + "3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f");
localHttpURLConnection.setDoOutput(true);
localHttpURLConnection.setDoInput(true);
localHttpURLConnection.setRequestProperty("Connection", "Keep-Alive");
localHttpURLConnection.connect();
Đây là một đoạn xử lý khi ứng dụng muốn gửi 1 request lên ứng dụng facebook ( vì Zalo và WeChat đều có facebook integration ) nằm trong bộ Facebook-Sdk (File version nằm ở src/com/facebook/FacebookSdkVersion.java )
Một điều thú vị nữa khi đọc đoạn code này là dường như cả Zalo và WeChat đều không sử dụng giao thức HTTPS
Kết luận của tôi tạm thời hiện nay qua việc kiểm tra mã nguồn thì tuy có 1 số trùng lặp trong code nhưng điều đó chưa chứng tỏ được Zalo có sử dụng mã nguổn sao chép từ WeChat.
Để khẳng định rõ hơn nữa thì cần phải tiếp tục rà soát các yếu tố trong các tính năng chính của cả 2 bên, phần bộ nhớ lúc thực thi (phần sau sẽ hướng dẫn sử dụng debugger cho android) và các phần mã bị làm rối mà jd-gui không dịch ngược lại được. ( Chẳng hạn : WeChat/src/unk/com/tencent/mm/sdk/platformtools/bg.java :1272 )
Keyboard heroes detected
Trong topic bên HVA có ghi rõ ràng:
Found a 10 line (86 tokens) duplication in the following files: Starting at line 131 of ./src/ZaloRE/src/com/facebook/android/Util.java Starting at line 62 of ./src/WeChat/src/unk/com/tencent/mm/ui/facebook/a/m.java Found a 5 line (70 tokens) duplication in the following files: Starting at line 87 of ./src/ZaloRE/src/unk/com/a/b/e.java Starting at line 155 of ./src/WeChat/src/unk/com/tencent/mm/sdk/platformtools/bg.java Found a 5 line (69 tokens) duplication in the following files: Starting at line 87 of ./src/ZaloRE/src/unk/com/a/b/e.java Starting at line 562 of ./src/WeChat/src/unk/com/tencent/mm/platformtools/bf.java Found a 16 line (65 tokens) duplication in the following files: Starting at line 81 of ./src/ZaloRE/src/unk/com/zing/zalo/uicontrol/w.java Starting at line 55 of ./src/WeChat/src/unk/com/tencent/mm/modelemoji/l.java Found a 11 line (59 tokens) duplication in the following files: Starting at line 21 of ./src/ZaloRE/src/me/zing/vn/gl/FilterGLSurfaceView$ConfigChooser.java Starting at line 21 of ./src/WeChat/src/unk/com/badlogic/gdx/backends/android/w.java Found a 13 line (59 tokens) duplication in the following files: Starting at line 161 of ./src/ZaloRE/src/com/zing/zalo/uicontrol/HorizontalPager.java Starting at line 148 of ./src/WeChat/src/com/tencent/mm/ui/base/MMFlipper.java Found a 16 line (55 tokens) duplication in the following files: Starting at line 12 of ./src/ZaloRE/src/unk/com/zing/zalo/plugin/a.java Starting at line 36 of ./src/WeChat/src/com/android/internal/telephony/ISms$Stub.java |
Nói chung câu chuyện vẫn chưa có gì , vì trang hvaonline cũng như các trang khác đều không cập nhật nữa. Thông tin để các bạn tham khảo về code từ rất lâu của Zalo
Nguồn tham khảo hvaonline hvaonline.net/hvaonline/posts/list/44782.hva#276069