mirror of
https://github.com/xweiba/location-spoofer.git
synced 2026-09-21 22:30:46 +08:00
feat: unify app and third-party wloc features
This commit is contained in:
+15
-1
@@ -55,6 +55,11 @@ func wloccore_validateca(certData, keyData *C.char) C.int {
|
||||
|
||||
//export wloccore_startproxy
|
||||
func wloccore_startproxy(certData, keyData *C.char, lat, lon C.double, enabled C.int, accuracy C.int) C.uintptr_t {
|
||||
return wloccore_startproxyv2(certData, keyData, lat, lon, enabled, accuracy, 0)
|
||||
}
|
||||
|
||||
//export wloccore_startproxyv2
|
||||
func wloccore_startproxyv2(certData, keyData *C.char, lat, lon C.double, enabled C.int, accuracy C.int, motionEnabled C.int) C.uintptr_t {
|
||||
if certData == nil || keyData == nil {
|
||||
return 0
|
||||
}
|
||||
@@ -65,6 +70,7 @@ func wloccore_startproxy(certData, keyData *C.char, lat, lon C.double, enabled C
|
||||
float64(lon),
|
||||
enabled != 0,
|
||||
int(accuracy),
|
||||
motionEnabled != 0,
|
||||
)
|
||||
if err != nil {
|
||||
logEvent("startproxy failed: " + err.Error())
|
||||
@@ -106,13 +112,21 @@ func proxyForHandle(h C.uintptr_t) (server *http.Server, handle cgo.Handle, ok b
|
||||
|
||||
//export wloccore_setcoords
|
||||
func wloccore_setcoords(lat, lon C.double, enabled C.int, accuracy C.int) {
|
||||
wloccore_setpatchconfig(lat, lon, enabled, accuracy, 0)
|
||||
}
|
||||
|
||||
//export wloccore_setpatchconfig
|
||||
func wloccore_setpatchconfig(lat, lon C.double, enabled C.int, accuracy C.int, motionEnabled C.int) {
|
||||
stateMu.Lock()
|
||||
currentLat = float64(lat)
|
||||
currentLon = float64(lon)
|
||||
currentEnabled = enabled != 0
|
||||
currentAccuracy = int(accuracy)
|
||||
currentMotionSimulationEnabled = motionEnabled != 0
|
||||
stateMu.Unlock()
|
||||
logEvent("setcoords enabled=" + strconv.FormatBool(enabled != 0) + " accuracy=" + strconv.Itoa(int(accuracy)))
|
||||
logEvent("setpatchconfig enabled=" + strconv.FormatBool(enabled != 0) +
|
||||
" accuracy=" + strconv.Itoa(int(accuracy)) +
|
||||
" motion=" + strconv.FormatBool(motionEnabled != 0))
|
||||
}
|
||||
|
||||
//export wloccore_getcoords
|
||||
|
||||
+17
-12
@@ -22,13 +22,14 @@ import (
|
||||
const proxyPort = 8888
|
||||
|
||||
var (
|
||||
stateMu sync.Mutex
|
||||
currentLat float64
|
||||
currentLon float64
|
||||
currentEnabled bool
|
||||
currentAccuracy int
|
||||
globalCACert *tls.Certificate
|
||||
verifyToken string
|
||||
stateMu sync.Mutex
|
||||
currentLat float64
|
||||
currentLon float64
|
||||
currentEnabled bool
|
||||
currentAccuracy int
|
||||
currentMotionSimulationEnabled bool
|
||||
globalCACert *tls.Certificate
|
||||
verifyToken string
|
||||
|
||||
logMu sync.Mutex
|
||||
logEntries []string
|
||||
@@ -94,10 +95,10 @@ func newProxy(cert *tls.Certificate) *goproxy.ProxyHttpServer {
|
||||
}
|
||||
if r.URL.Path == "/coords" {
|
||||
stateMu.Lock()
|
||||
enabled, lat, lon, accuracy := currentEnabled, currentLat, currentLon, currentAccuracy
|
||||
enabled, lat, lon, accuracy, motionEnabled := currentEnabled, currentLat, currentLon, currentAccuracy, currentMotionSimulationEnabled
|
||||
stateMu.Unlock()
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write([]byte(fmt.Sprintf(`{"enabled":%t,"lat":%.6f,"lon":%.6f,"accuracy":%d}`, enabled, lat, lon, accuracy)))
|
||||
w.Write([]byte(fmt.Sprintf(`{"enabled":%t,"lat":%.6f,"lon":%.6f,"accuracy":%d,"motionSimulationEnabled":%t}`, enabled, lat, lon, accuracy, motionEnabled)))
|
||||
return
|
||||
}
|
||||
if r.URL.Path == "/proxy.mobileconfig" || r.URL.Path == "/proxy.mobileconfig/" {
|
||||
@@ -221,7 +222,7 @@ func patchWlocResponse(resp *http.Response, ctx *goproxy.ProxyCtx) *http.Respons
|
||||
}
|
||||
|
||||
stateMu.Lock()
|
||||
enabled, lat, lon, accuracy := currentEnabled, currentLat, currentLon, currentAccuracy
|
||||
enabled, lat, lon, accuracy, motionEnabled := currentEnabled, currentLat, currentLon, currentAccuracy, currentMotionSimulationEnabled
|
||||
stateMu.Unlock()
|
||||
|
||||
const maxPatchBodyBytes int64 = 1 << 20
|
||||
@@ -249,7 +250,10 @@ func patchWlocResponse(resp *http.Response, ctx *goproxy.ProxyCtx) *http.Respons
|
||||
return resp
|
||||
}
|
||||
|
||||
patched, stats, err := patchResponseBody(body, wlocCoords{Latitude: lat, Longitude: lon, Accuracy: accuracy})
|
||||
patched, stats, err := patchResponseBody(body, wlocCoords{
|
||||
Latitude: lat, Longitude: lon, Accuracy: accuracy,
|
||||
MotionSimulationEnabled: motionEnabled,
|
||||
})
|
||||
if err != nil || bytes.Equal(patched, body) {
|
||||
if err != nil {
|
||||
logEvent("wloc patch skipped: " + err.Error())
|
||||
@@ -326,7 +330,7 @@ func randomUint32() uint32 {
|
||||
return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
|
||||
}
|
||||
|
||||
func startProxy(certPEM, keyPEM []byte, lat, lon float64, enabled bool, accuracy int) (*http.Server, error) {
|
||||
func startProxy(certPEM, keyPEM []byte, lat, lon float64, enabled bool, accuracy int, motionEnabled bool) (*http.Server, error) {
|
||||
cert, err := parseCA(certPEM, keyPEM)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -335,6 +339,7 @@ func startProxy(certPEM, keyPEM []byte, lat, lon float64, enabled bool, accuracy
|
||||
stateMu.Lock()
|
||||
globalCACert = cert
|
||||
currentLat, currentLon, currentEnabled, currentAccuracy = lat, lon, enabled, accuracy
|
||||
currentMotionSimulationEnabled = motionEnabled
|
||||
stateMu.Unlock()
|
||||
|
||||
listener, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", proxyPort))
|
||||
|
||||
+34
-3
@@ -20,11 +20,17 @@ const (
|
||||
)
|
||||
|
||||
type wlocCoords struct {
|
||||
Latitude float64
|
||||
Longitude float64
|
||||
Accuracy int
|
||||
Latitude float64
|
||||
Longitude float64
|
||||
Accuracy int
|
||||
MotionSimulationEnabled bool
|
||||
}
|
||||
|
||||
const (
|
||||
motionActivityType = 63
|
||||
motionActivityConfidence = 467
|
||||
)
|
||||
|
||||
type patchStats struct {
|
||||
WiFi int
|
||||
Cell int
|
||||
@@ -179,6 +185,7 @@ func patchLocation(loc []byte, c wlocCoords) ([]byte, bool, error) {
|
||||
lon := int64(math.Round(c.Longitude * 1e8))
|
||||
var out []byte
|
||||
changed := false
|
||||
hasMotionType, hasMotionConfidence := false, false
|
||||
for _, f := range fields {
|
||||
switch {
|
||||
case f.num == 1 && f.wireType == wireVarint:
|
||||
@@ -199,10 +206,34 @@ func patchLocation(loc []byte, c wlocCoords) ([]byte, bool, error) {
|
||||
changed = true
|
||||
}
|
||||
out = append(out, raw...)
|
||||
case c.MotionSimulationEnabled && f.num == 11 && f.wireType == wireVarint:
|
||||
hasMotionType = true
|
||||
raw := append(writeTag(11, wireVarint), writeVarint(motionActivityType)...)
|
||||
if !bytes.Equal(raw, f.raw) {
|
||||
changed = true
|
||||
}
|
||||
out = append(out, raw...)
|
||||
case c.MotionSimulationEnabled && f.num == 12 && f.wireType == wireVarint:
|
||||
hasMotionConfidence = true
|
||||
raw := append(writeTag(12, wireVarint), writeVarint(motionActivityConfidence)...)
|
||||
if !bytes.Equal(raw, f.raw) {
|
||||
changed = true
|
||||
}
|
||||
out = append(out, raw...)
|
||||
default:
|
||||
out = append(out, f.raw...)
|
||||
}
|
||||
}
|
||||
if c.MotionSimulationEnabled && !hasMotionType {
|
||||
out = append(out, writeTag(11, wireVarint)...)
|
||||
out = append(out, writeVarint(motionActivityType)...)
|
||||
changed = true
|
||||
}
|
||||
if c.MotionSimulationEnabled && !hasMotionConfidence {
|
||||
out = append(out, writeTag(12, wireVarint)...)
|
||||
out = append(out, writeVarint(motionActivityConfidence)...)
|
||||
changed = true
|
||||
}
|
||||
return out, changed, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,15 @@ func testLocation(lat, lon int64, accuracy uint64) []byte {
|
||||
return out
|
||||
}
|
||||
|
||||
func testLocationWithMotion(lat, lon int64, accuracy, motionType, motionConfidence uint64) []byte {
|
||||
out := testLocation(lat, lon, accuracy)
|
||||
out = append(out, writeTag(11, wireVarint)...)
|
||||
out = append(out, writeVarint(motionType)...)
|
||||
out = append(out, writeTag(12, wireVarint)...)
|
||||
out = append(out, writeVarint(motionConfidence)...)
|
||||
return out
|
||||
}
|
||||
|
||||
func testWifiDevice(loc []byte) []byte {
|
||||
mac := []byte("aa:bb:cc:dd:ee:ff")
|
||||
var out []byte
|
||||
@@ -113,6 +122,66 @@ func TestPatchCellLocation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMotionSimulationDisabledPreservesFields(t *testing.T) {
|
||||
original := testLocationWithMotion(100, 200, 25, 7, 88)
|
||||
patched, changed, err := patchLocation(original, wlocCoords{
|
||||
Latitude: 31.230416, Longitude: 121.473701, Accuracy: 50,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !changed {
|
||||
t.Fatal("coordinates were not patched")
|
||||
}
|
||||
fields, err := parseFields(patched)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, field := range fields {
|
||||
if (field.num == 11 || field.num == 12) && !bytes.Contains(original, field.raw) {
|
||||
t.Fatalf("motion field %d changed while disabled", field.num)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMotionSimulationEnabledReplacesFields(t *testing.T) {
|
||||
original := testLocationWithMotion(100, 200, 25, 7, 88)
|
||||
patched, _, err := patchLocation(original, wlocCoords{
|
||||
Latitude: 31.230416, Longitude: 121.473701, Accuracy: 50,
|
||||
MotionSimulationEnabled: true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Contains(patched, append(writeTag(11, wireVarint), writeVarint(motionActivityType)...)) {
|
||||
t.Fatal("motion activity type was not replaced")
|
||||
}
|
||||
if !bytes.Contains(patched, append(writeTag(12, wireVarint), writeVarint(motionActivityConfidence)...)) {
|
||||
t.Fatal("motion activity confidence was not replaced")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMotionSimulationEnabledAddsMissingFields(t *testing.T) {
|
||||
patched, _, err := patchLocation(testLocation(100, 200, 25), wlocCoords{
|
||||
Latitude: 31.230416, Longitude: 121.473701, Accuracy: 50,
|
||||
MotionSimulationEnabled: true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fields, err := parseFields(patched)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
counts := map[int]int{}
|
||||
for _, field := range fields {
|
||||
counts[field.num]++
|
||||
}
|
||||
if counts[11] != 1 || counts[12] != 1 {
|
||||
t.Fatalf("expected one inserted motion field each, got %+v", counts)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPatchARPCFramePreservesEnvelopeAndSuffix(t *testing.T) {
|
||||
payload := writeLengthDelimited(2, testWifiDevice(testLocation(100, 200, 25)))
|
||||
suffix := []byte{0xde, 0xad, 0xbe, 0xef}
|
||||
|
||||
Reference in New Issue
Block a user