Skip to content

Instantly share code, notes, and snippets.

@LuaxY
Last active November 15, 2023 03:52
Show Gist options
  • Save LuaxY/9186302f591770c8f5658cdf4515c9c7 to your computer and use it in GitHub Desktop.
Save LuaxY/9186302f591770c8f5658cdf4515c9c7 to your computer and use it in GitHub Desktop.
QIUI App Patch

CellMate Qiui

Remove unlock verification

# 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

Proxy (useful for debugging)

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)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment