mirror of
https://github.com/xweiba/location-spoofer.git
synced 2026-09-22 06:40:44 +08:00
- iOS 虚拟定位工具,基于本地 HTTP 代理 MITM 方案 - MapKit 原生地图体验,支持搜索、收藏、实时定位 - 完整的设置引导流程(证书安装、WiFi 代理配置、环境验证) - 支持 iOS 15+,SwiftUI 构建
226 lines
5.7 KiB
Go
226 lines
5.7 KiB
Go
package main
|
|
|
|
/*
|
|
#cgo CFLAGS: -DGOOS_ios -DNDEBUG
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
*/
|
|
import "C"
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"math"
|
|
"net"
|
|
"net/http"
|
|
"runtime/cgo"
|
|
"strconv"
|
|
)
|
|
|
|
//export wloccore_init
|
|
func wloccore_init() {}
|
|
|
|
//export wloccore_hello
|
|
func wloccore_hello() {}
|
|
|
|
//export wloccore_version
|
|
func wloccore_version() *C.char {
|
|
return C.CString("0.1.0")
|
|
}
|
|
|
|
//export wloccore_generateca
|
|
func wloccore_generateca() (r0, r1 *C.char) {
|
|
logEvent("generateca started")
|
|
cert, key, err := generateCA()
|
|
if err != nil {
|
|
logEvent("generateca failed: " + err.Error())
|
|
return nil, nil
|
|
}
|
|
logEvent("generateca completed")
|
|
return C.CString(string(cert)), C.CString(string(key))
|
|
}
|
|
|
|
//export wloccore_startproxy
|
|
func wloccore_startproxy(certData, keyData *C.char, lat, lon C.double, enabled C.int, accuracy C.int) C.uintptr_t {
|
|
if certData == nil || keyData == nil {
|
|
return 0
|
|
}
|
|
srv, err := startProxy(
|
|
[]byte(C.GoString(certData)),
|
|
[]byte(C.GoString(keyData)),
|
|
float64(lat),
|
|
float64(lon),
|
|
enabled != 0,
|
|
int(accuracy),
|
|
)
|
|
if err != nil {
|
|
logEvent("startproxy failed: " + err.Error())
|
|
return 0
|
|
}
|
|
return C.uintptr_t(cgo.NewHandle(srv))
|
|
}
|
|
|
|
//export wloccore_stopproxy
|
|
func wloccore_stopproxy(h C.uintptr_t) C.int {
|
|
logEvent("stopproxy requested")
|
|
handle := cgo.Handle(h)
|
|
srv, ok := handle.Value().(*http.Server)
|
|
handle.Delete()
|
|
if !ok {
|
|
logEvent("stopproxy failed: invalid handle")
|
|
return 1
|
|
}
|
|
if err := stopProxy(srv); err != nil {
|
|
logEvent("stopproxy failed: " + err.Error())
|
|
return 2
|
|
}
|
|
logEvent("stopproxy completed")
|
|
return 0
|
|
}
|
|
|
|
//export wloccore_setcoords
|
|
func wloccore_setcoords(lat, lon C.double, enabled C.int, accuracy C.int) {
|
|
stateMu.Lock()
|
|
currentLat = float64(lat)
|
|
currentLon = float64(lon)
|
|
currentEnabled = enabled != 0
|
|
currentAccuracy = int(accuracy)
|
|
stateMu.Unlock()
|
|
logEvent("setcoords enabled=" + strconv.FormatBool(enabled != 0) + " lat=" + strconv.FormatFloat(float64(lat), 'f', 6, 64) + " lon=" + strconv.FormatFloat(float64(lon), 'f', 6, 64) + " accuracy=" + strconv.Itoa(int(accuracy)))
|
|
}
|
|
|
|
//export wloccore_getcoords
|
|
func wloccore_getcoords() (lat, lon C.double, enabled C.int) {
|
|
stateMu.Lock()
|
|
defer stateMu.Unlock()
|
|
lat = C.double(currentLat)
|
|
lon = C.double(currentLon)
|
|
enabled = 0
|
|
if currentEnabled {
|
|
enabled = 1
|
|
}
|
|
return lat, lon, enabled
|
|
}
|
|
|
|
//export wloccore_drainlogs
|
|
func wloccore_drainlogs() *C.char {
|
|
s := drainLogs()
|
|
if s == "" {
|
|
return nil
|
|
}
|
|
return C.CString(s)
|
|
}
|
|
|
|
//export wloccore_startcertserver
|
|
func wloccore_startcertserver(certData, keyData *C.char) C.uintptr_t {
|
|
if certData == nil || keyData == nil {
|
|
return 0
|
|
}
|
|
logEvent("start certificate server requested")
|
|
server, err := startCertificateServer([]byte(C.GoString(certData)), []byte(C.GoString(keyData)))
|
|
if err != nil {
|
|
logEvent("start certificate server failed: " + err.Error())
|
|
return 0
|
|
}
|
|
logEvent("certificate server started http=" + server.DownloadURL() + " probe=" + server.ProbeURL())
|
|
return C.uintptr_t(cgo.NewHandle(server))
|
|
}
|
|
|
|
func certificateServerForHandle(h C.uintptr_t) (*certificateServer, cgo.Handle, bool) {
|
|
if h == 0 {
|
|
return nil, 0, false
|
|
}
|
|
handle := cgo.Handle(h)
|
|
server, ok := handle.Value().(*certificateServer)
|
|
return server, handle, ok
|
|
}
|
|
|
|
//export wloccore_certserver_httpport
|
|
func wloccore_certserver_httpport(h C.uintptr_t) C.int {
|
|
server, _, ok := certificateServerForHandle(h)
|
|
if !ok {
|
|
return 0
|
|
}
|
|
return C.int(server.httpLn.Addr().(*net.TCPAddr).Port)
|
|
}
|
|
|
|
//export wloccore_certserver_httpsport
|
|
func wloccore_certserver_httpsport(h C.uintptr_t) C.int {
|
|
server, _, ok := certificateServerForHandle(h)
|
|
if !ok {
|
|
return 0
|
|
}
|
|
return C.int(server.httpsLn.Addr().(*net.TCPAddr).Port)
|
|
}
|
|
|
|
//export wloccore_certserver_leafsha256
|
|
func wloccore_certserver_leafsha256(h C.uintptr_t) *C.char {
|
|
server, _, ok := certificateServerForHandle(h)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return C.CString(server.LeafSHA256())
|
|
}
|
|
|
|
//export wloccore_stopcertserver
|
|
func wloccore_stopcertserver(h C.uintptr_t) C.int {
|
|
server, handle, ok := certificateServerForHandle(h)
|
|
if !ok {
|
|
return 1
|
|
}
|
|
handle.Delete()
|
|
if err := server.Close(); err != nil {
|
|
return 2
|
|
}
|
|
return 0
|
|
}
|
|
|
|
//export wloccore_testpatch
|
|
func wloccore_testpatch(lat, lon C.double, accuracy C.int) *C.char {
|
|
c := wlocCoords{Latitude: float64(lat), Longitude: float64(lon), Accuracy: int(accuracy)}
|
|
original := makeTestWlocBody()
|
|
patched, stats, err := patchWlocBody(original, c)
|
|
if err != nil {
|
|
return C.CString("error: " + err.Error())
|
|
}
|
|
if stats.Locations == 0 {
|
|
return C.CString("error: no location entries found")
|
|
}
|
|
if len(patched) < 10 {
|
|
return C.CString("error: patched body too short")
|
|
}
|
|
newLen := int(binary.BigEndian.Uint16(patched[8:10]))
|
|
if newLen <= 0 || 10+newLen > len(patched) {
|
|
return C.CString("error: invalid patched length")
|
|
}
|
|
newPayload := patched[10 : 10+newLen]
|
|
wantLat := append(writeTag(1, wireVarint), writeVarint(uint64(int64(math.Round(c.Latitude*1e8))))...)
|
|
wantLon := append(writeTag(2, wireVarint), writeVarint(uint64(int64(math.Round(c.Longitude*1e8))))...)
|
|
if !bytes.Contains(newPayload, wantLat) {
|
|
return C.CString("error: patched latitude mismatch")
|
|
}
|
|
if !bytes.Contains(newPayload, wantLon) {
|
|
return C.CString("error: patched longitude mismatch")
|
|
}
|
|
return C.CString(fmt.Sprintf("ok: lat=%f lon=%f wifi=%d cell=%d locations=%d", c.Latitude, c.Longitude, stats.WiFi, stats.Cell, stats.Locations))
|
|
}
|
|
|
|
//export wloccore_testrequesthex
|
|
func wloccore_testrequesthex() *C.char {
|
|
return C.CString(fmt.Sprintf("%x", makeTestWlocRequest()))
|
|
}
|
|
|
|
//export wloccore_refreshverifytoken
|
|
func wloccore_refreshverifytoken() *C.char {
|
|
return C.CString(refreshVerifyToken())
|
|
}
|
|
|
|
//export wloccore_checkverifytoken
|
|
func wloccore_checkverifytoken(token *C.char) C.int {
|
|
if checkVerifyToken(C.GoString(token)) {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|