# Decompile apk
apktool d qiui.googlestore.dif.apk
Edit assets/widget/html/main/deviceDetail-frm.html
to remove unlock verification
function openLock(){
if(api.connectionType == 'none'){
showToast($.i18n.prop('networkAnomaly'));
return;
}
ajaxRequest('member/DeviceBinding/checkPower', {
deviceCode: vm.deviceCode + "",
memberCode: $api.getStorage('memberInfo').memberCode + ""
}, function(res) {
console.log(JSON.stringify(res));
vm.memberPower = res.DeviceBinding.memberPower
vm.effective = res.DeviceBinding.effective
if(vm.effective - 0 == 0){
showToast($.i18n.prop('noPower'))
return;
}
ajaxRequest('member/DeviceInfo/getTimingByCode', {
deviceCode: vm.deviceCode + ""
}, function(res) {
/*if(res.isEnding){
showToast($.i18n.prop('fixedTime'))
return;
}else{*/
$(".modal").show();
if(vm.deviceReturn.token){
ajaxRequest('member/DeviceInfo/getHexCommand', {
encrypt: vm.encrypt || 0,
hexStr: "050106303030303030"+vm.deviceReturn.token+"002E00"
}, function(res) {
writeValueForCharacteristic(res.message, 0);
}, "POST");
}else{
initBle();
openTimer = setInterval(function(){
if(vm.deviceReturn.token){
clearInterval(openTimer)
ajaxRequest('member/DeviceInfo/getHexCommand', {
encrypt: vm.encrypt || 0,
hexStr: "050106303030303030"+vm.deviceReturn.token+"002E00"
}, function(res) {
writeValueForCharacteristic(res.message, 0);
}, "POST");
}
}, 500);
}
/*}*/
}, "POST");
}, "POST");
}
# Build patched apk
apktool b qiui.googlestore.dif -o unlock.apk
# Generate self-signed certificate keystore
keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
# Sign apk
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore unlock.apk alias_name
# Push apk to phone
adb push unlock.apk /sdcard
Edit assets/widget/script/common.js
to proxify traffic
var contextPath = "http://192.168.0.11:8080/qiui/";
Go reverse proxy example
package main
import (
"bytes"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/httputil"
"net/url"
"strconv"
)
var proxy *httputil.ReverseProxy
func main() {
port := flag.Int("port", 8080, "port to listen on")
targetURL := flag.String("target-url", "http://qiuitoy.com/", "downstream service url to proxy to")
flag.Parse()
u, err := url.Parse(*targetURL)
if err != nil {
log.Fatalf("Could not parse downstream url: %s", *targetURL)
}
proxy = httputil.NewSingleHostReverseProxy(u)
director := proxy.Director
proxy.Director = func(req *http.Request) {
director(req)
//req.Header.Set("X-Forwarded-Host", req.Header.Get("Host"))
req.Host = req.URL.Host
}
proxy.ModifyResponse = func(res *http.Response) error {
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
res.Body.Close()
fmt.Println(string(body))
res.Body = ioutil.NopCloser(bytes.NewBuffer(body))
return nil
}
http.HandleFunc("/other", proxy.ServeHTTP)
http.HandleFunc("/", handler)
log.Printf("Listening on port %d", *port)
log.Fatal(http.ListenAndServe(":"+strconv.Itoa(*port), nil))
}
func handler(rw http.ResponseWriter, req *http.Request) {
log.Println("Froward", req.Method, req.RequestURI)
body, err := ioutil.ReadAll(req.Body)
if err != nil {
http.Error(rw, fmt.Sprintf("Error reading body: %s", err), 500)
return
}
req.Body.Close()
fmt.Println(string(body))
req.Body = ioutil.NopCloser(bytes.NewBuffer(body))
proxy.ServeHTTP(rw, req)
}