Initial
This commit is contained in:
92
src_win/actions-iTunes-header/action.yml
Executable file
92
src_win/actions-iTunes-header/action.yml
Executable file
@@ -0,0 +1,92 @@
|
||||
name: 'Get iTunes Headers & Kbsync'
|
||||
inputs:
|
||||
apple_id:
|
||||
required: true
|
||||
apple_id_pwd:
|
||||
required: true
|
||||
ngrok_token:
|
||||
description: "Token for RDP debugging"
|
||||
required: false
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Check if initialized
|
||||
id: check
|
||||
run: |
|
||||
echo "Checking if we need to initialize iTunes again"
|
||||
if [[ "$(cat /c/.iTunesInitialized)" == "${{ inputs.ngrok-token }}" ]]; then
|
||||
echo " Need to re-init iTunes"
|
||||
echo "NEED_INIT=1" >> $GITHUB_ENV
|
||||
else
|
||||
echo " Needn't to do anything"
|
||||
echo "NEED_INIT=0" >> $GITHUB_ENV
|
||||
fi
|
||||
working-directory: ${{ github.action_path }}
|
||||
shell: bash
|
||||
- name: Setup iTunes
|
||||
if: ${{ env.NEED_INIT == 1 }}
|
||||
run: |
|
||||
echo Setup iTunes...
|
||||
start /wait taskkill /f /im iTunes* python*
|
||||
workflow_helper\iTunesInstall\install_itunes.bat
|
||||
working-directory: ${{ github.action_path }}
|
||||
shell: cmd
|
||||
|
||||
- name: Setup Python Dependencies
|
||||
if: ${{ env.NEED_INIT == 1 }}
|
||||
run: |
|
||||
echo Setup Python Dependencies...
|
||||
pip3 install pywinauto frida Flask
|
||||
working-directory: ${{ github.action_path }}
|
||||
shell: cmd
|
||||
|
||||
#- uses: NyaMisty/reverse-rdp-windows-github-actions-ng@master
|
||||
# if: ${{ always() && github.event_name == 'workflow_dispatch' && github.event.inputs.itunes_debug_enabled }}
|
||||
# with:
|
||||
# ngrok-token: ${{ inputs.ngrok_token }}
|
||||
# password: Aa123456
|
||||
# foreground: false
|
||||
|
||||
- name: Login iTunes
|
||||
if: ${{ env.NEED_INIT == 1 }}
|
||||
env:
|
||||
APPLEID: ${{ inputs.apple_id }}
|
||||
APPLEID_PWD: ${{ inputs.apple_id_pwd }}
|
||||
run: |
|
||||
echo Login iTunes...
|
||||
python3 workflow_helper/itunes_auto_login.py %APPLEID% %APPLEID_PWD%
|
||||
working-directory: ${{ github.action_path }}
|
||||
shell: cmd
|
||||
|
||||
- name: Finish Initialization
|
||||
if: ${{ env.NEED_INIT == 1 }}
|
||||
env:
|
||||
APPLEID: ${{ inputs.apple_id }}
|
||||
run: |
|
||||
echo "Finish Initialization..."
|
||||
echo "$APPLEID" > /c/.iTunesInitialized
|
||||
working-directory: ${{ github.action_path }}
|
||||
shell: bash
|
||||
|
||||
- name: Start Frida Header Server
|
||||
run: |
|
||||
echo Start Frida Header Server!
|
||||
curl -Lo psexec64.exe https://github.com/ComputerGuyYash/psexec/raw/main/PsExec64.exe
|
||||
psexec64.exe -accepteula -nobanner -i -d cmd /c "python3.exe workflow_helper/iTunesDownload/get_header.py > C:\get_header.log 2>&1"
|
||||
exit 0
|
||||
working-directory: ${{ github.action_path }}
|
||||
shell: cmd
|
||||
|
||||
- name: Test Frida Header Server
|
||||
run: |
|
||||
sleep 5
|
||||
ret=0
|
||||
echo "---------------- Before query headers ----------------"
|
||||
cat /c/get_header.log
|
||||
curl --fail-with-body -vv 127.0.0.1:9000 || ret=$?
|
||||
echo "---------------- After query headers ----------------"
|
||||
cat /c/get_header.log
|
||||
exit $ret
|
||||
working-directory: ${{ github.action_path }}
|
||||
shell: bash
|
||||
22
src_win/actions-iTunes-header/patch_itunes.py
Executable file
22
src_win/actions-iTunes-header/patch_itunes.py
Executable file
@@ -0,0 +1,22 @@
|
||||
import os
|
||||
|
||||
# for debug
|
||||
P = r"C:\Program Files\iTunes\iTunes1.exe"
|
||||
if not os.path.exists(P):
|
||||
# for production
|
||||
P = r"C:\Program Files\iTunes\iTunes.exe"
|
||||
|
||||
with open(P, 'rb') as f:
|
||||
data = f.read()
|
||||
|
||||
data = bytearray(data)
|
||||
|
||||
# Patch passwordSettings (actually useless)
|
||||
data[0x77daf4:0x77daf4+5] = b'\xBF\x03\x00\x00\x00'
|
||||
data[0x77db7e:0x77db7e+2] = b'\xEB\x0A'
|
||||
|
||||
# Patch signIn reason to serverDialog
|
||||
data[0x7a9ed4:0x7a9ed4+6] = b'\xB9\x23\xFF\xFF\xFF\x90'
|
||||
|
||||
with open(P, 'wb') as f:
|
||||
f.write(data)
|
||||
113
src_win/actions-iTunes-header/workflow_helper/iTunesDownload/get_header.py
Executable file
113
src_win/actions-iTunes-header/workflow_helper/iTunesDownload/get_header.py
Executable file
@@ -0,0 +1,113 @@
|
||||
# frida_rpc_player.py
|
||||
|
||||
'''
|
||||
POST /WebObjects/MZBuy.woa/wa/buyProduct HTTP/1.1
|
||||
Host: p46-buy.itunes.apple.com
|
||||
User-Agent: iTunes/12.6.5 (Windows; Microsoft Windows 10.0 x64 Enterprise Edition (Build 19042); x64) AppleWebKit/7605.1033.1002.2
|
||||
Content-Length: 1226
|
||||
Content-Type: application/x-apple-plist
|
||||
X-Dsid: 12263680861
|
||||
X-Apple-Tz: 28800
|
||||
X-Apple-MD: AAAABAAAABA3hIN/KYf4Ri4tdZAiwaB5
|
||||
Cookie: amp=JG7EpvImu+/h0yS5mTqQMLarQce6xuYNfyzC6cun/bRt+7VLQUqfUrDB4cdRyV6SLDGBRCG3Oz/PcY28nx94GdTGkdOYX83a54KHZTSq3jI=; amia-12263680861=dPQK5oK/9b6q7HeGIids4a6gE5oiE8yLcVjQO7EknSTERhI0OawL4FQcmJ60560H+PbZhCCt6Na8jLSDiU09aw==; mt-asn-12263680861=2; mt-tkn-12263680861=AmDauzfLChTup9vGq17bGVJvSurhbsyoCLyrpJG8t8uECuyAI3xr3o/vS9pVpKeg4dSlCxJtLUS8+H47Qtpou0VGgGBAn/dXAPozhdJKTyPdUqyT4My89dujXg48XNgIVUjFj2w4IhN1gg5wn3BfSg1bFChodxuHadsRibnYzkUPmR+TVTnivu9e4/QLJmh58Va8rmg=; mt-tkn-10255130069=Ala2nKdNzZWOlapGgvRzcNExINc8j4sbrcMn3ruJ9M3Cb17MGiGqvyTe9yUzh/fSNLEL+4s0j57Eht/AWXrG2e3+GptHZlTi1vZ4a+3PdD9dtfSP8no7s9/bMX6JTtnE+fwV1z8QudsvAs+kjEz0MqFgoxFZZntBKI1L81+CBTnmsBolRdk+wqqPGZ3AD5bdybUTwD4=; countryVerified=1; mzf_in=467080; itspod=46; vrep=CN3W49ctEgQIChAAEgQICBAAEgQIBxAAEgQIBBAAEgQIDRAAEgQIBhAAEgQIDBAAEgQIAxAAEgQICRAAEgQIEBAAEgQIDhAAEgQIARAAEgQIDxAAEgQIERAAEgQIBRAAEgQICxAAEgQIAhAA; wosid-lite=jRoFTHWbZZZkSOfvfDELf0; mz_at_ssl-12263680861=AwUAAAECAAHXHQAAAABgqAeMT5/7LbF5106/zxFn9xH4n7jgwEw=; mz_at0-12263680861=AwQAAAECAAHXHQAAAABgp/7Z1enk1z4615lhp9QKlDQfmo7Hq60=; pldfltcid=524b36a58d0d4249a127affd05921dab046; X-Dsid=12263680861; xp_ab=1#WqjkRLH+-2+TCEF_ea00#yNFpB6B+-2+c9imSgD01; xp_abc=TCEF_ea00; mz_at0-10255130069=AwQAAAECAAHXHQAAAABgnNBzeacT12/WPi/iSOROyaMVQrfmkqE=; mz_at_ssl-10255130069=AwUAAAECAAHXHQAAAABgnNBzNHT9PbcrsAARLEWi0+8ElnKZ54c=; xp_ci=3z3h6Y0vzFQQz4XtzB5DzZvQkYhyo
|
||||
X-Apple-AMD-M: rjK8HkwTcIoiOk6UoA9LXta0h/19+ss41RU7YLxGunAtLnl1Fus5i4VS56O71ifgDWwrEl/jIbPrDLfS
|
||||
X-Apple-AMD: AAAABAAAABCqItI0AgfIcPIc0+zGpNtr
|
||||
X-Apple-Store-Front: 143462-9,32
|
||||
Accept-Language: zh-cn
|
||||
Date: Fri, 21 May 2021 21:33:42 GMT
|
||||
X-Apple-MD-M: rjK8HkwTcIoiOk6UoA9LXta0h/2Qyn969daQuVAdJbkmCnWee7s+joaQ3fvc4v1JTJB0sUJcDwc0Q12z
|
||||
X-Apple-I-MD-RINFO: 50660608
|
||||
X-Apple-I-MD-M: rjK8HkwTcIoiOk6UoA9LXta0h/0W22FXNYql4KAM12/n20O3iVf54IK85PbrLb51CvEfn5/b6eoX5d1d
|
||||
X-Apple-I-MD: AAAABQAAABA+EMexoFPqOMeyQ5zIkQYPAAAAAg==
|
||||
Accept-Encoding: gzip, deflate
|
||||
Connection: close
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>guid</key>
|
||||
<string>46994789.C2E39C5C.B1D62DC2.025D2569.3D6E49B5.AB7F7EB4.F6D17565</string>
|
||||
<key>kbsync</key>
|
||||
<data>
|
||||
AAQAA5+HiDofKn/iW9aKVsKo1XU0cRuzPrQGMfC57fQaA7YaZBWlSS+s4SS2Ay6pchYG
|
||||
x/h+cJccHMoA/NDtHcWsRl9nmDwzAnuW9WH7nHQAEt95wkj2eMQVBHyj3OSkSoEGFnS8
|
||||
r4irSIve3V4np1lvbEUgHdJmOEV6gAd8SFzItmgxFImn55qoUX/xt4pdXagPmhBXaYFI
|
||||
+B/uYLxOYLO4fM1fGpQQ8/1EIpzrbahFjpG8L8kMjhVIWpn2Ut30p2deyjcL47JbSjx7
|
||||
/RId4XZlSEqXf9SOETcsxCkVhDWTghGYRWKlEe7j32CVrxOkg2lvlQLHB1XBhTpQiLSm
|
||||
PR0hDIG5dQif0jaIeQJ9zGqq3kgkl9RlFHGbcvfMdrJsYGOgYMzXh1jfF/v21xPfauYh
|
||||
PIE9LQu/TTiAGDvS+BYrM2xVaPHZPNUpLaVlk/2zIqiWo/Zj2se4FXGOl4LAVKqrbOYN
|
||||
2YONkSY4CQOZTmNmoO6SBU2NJHBYtVVeIhOLGLoS9/xzPwMdFevvZJFD7iQvL0RDKCBt
|
||||
z5r7dnFz2WlZsdx0aMsbV3HRdnJtmBh7zA3AaO/4rJtWAQqAID2gAF8YMoNdJJp13Bdr
|
||||
f34iRpVYbsDxrBNJXtanTgDdNO3xXpyZhQTgOrBDcsv7mD68E1E6bE5ac97/z9R8cLf0
|
||||
8/X8/ie7tUBcqVThW81DiM4RGh3LSg==
|
||||
</data>
|
||||
<key>price</key>
|
||||
<string>0</string>
|
||||
<key>pricingParameters</key>
|
||||
<string>STDRDL</string>
|
||||
<key>productType</key>
|
||||
<string>C</string>
|
||||
<key>salableAdamId</key>
|
||||
<string>1234806557</string><key>appExtVrsId</key>
|
||||
<string>839637337</string>
|
||||
</dict>
|
||||
</plist>
|
||||
'''
|
||||
|
||||
import sys
|
||||
import codecs
|
||||
import frida
|
||||
import plistlib
|
||||
import os
|
||||
import base64
|
||||
|
||||
##### Frida Part
|
||||
|
||||
procName = os.environ.get('ITUNES_PROCESS_NAME', 'iTunes.exe')
|
||||
session = frida.attach(procName)
|
||||
#session = frida.attach('iTunesFucked.exe')
|
||||
|
||||
def eprint(*args, **kwargs):
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
with codecs.open(os.path.dirname(os.path.realpath(__file__)) + '/get_header_rpc.js', 'r', 'utf-8') as f:
|
||||
source = f.read()
|
||||
|
||||
script = session.create_script(source)
|
||||
script.load()
|
||||
|
||||
def on_message(message, data):
|
||||
if message['type'] == 'send':
|
||||
eprint("Frida: %s" % message['payload'])
|
||||
elif message['type'] == 'error':
|
||||
eprint("Frida error: %s" % message['stack'])
|
||||
|
||||
script.on('message', on_message)
|
||||
|
||||
rpc = script.exports
|
||||
|
||||
|
||||
##### Flask Part
|
||||
|
||||
from flask import Flask, request
|
||||
from flask import jsonify
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/', methods=['GET', 'POST'])
|
||||
def getHeader():
|
||||
hdrUrl = request.args.get('url', "https://p46-buy.itunes.apple.com/WebObjects/MZBuy.woa/wa/buyProduct")
|
||||
retHdrs = rpc.get_header(hdrUrl)
|
||||
eprint("Got Headers: %s" % retHdrs)
|
||||
kbsync = retHdrs.pop('kbsync')
|
||||
guid = retHdrs.pop('X-Guid')
|
||||
return jsonify({
|
||||
"headers": retHdrs,
|
||||
"kbsync": kbsync,
|
||||
"guid": guid
|
||||
})
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0', port=9000)
|
||||
|
||||
session.detach()
|
||||
100
src_win/actions-iTunes-header/workflow_helper/iTunesDownload/get_header_rpc.js
Executable file
100
src_win/actions-iTunes-header/workflow_helper/iTunesDownload/get_header_rpc.js
Executable file
@@ -0,0 +1,100 @@
|
||||
var getHeader = null;
|
||||
function init() {
|
||||
var CFURLCreateWithBytes = new NativeFunction(Module.findExportByName('CoreFoundation','CFURLCreateWithBytes'), 'pointer', ['pointer', 'pointer', 'int64', 'int64', 'int64'])
|
||||
var CFDictionaryGetCount = new NativeFunction(Module.findExportByName('CoreFoundation','CFDictionaryGetCount'), 'int64', ['pointer'])
|
||||
var CFCopyDescription = new NativeFunction(Module.findExportByName('CoreFoundation','CFCopyDescription'), 'pointer', ['pointer'])
|
||||
var CFStringGetCStringPtr = new NativeFunction(Module.findExportByName('CoreFoundation','CFStringGetCStringPtr'), 'pointer', ['pointer', 'uint64'])
|
||||
var CFStringGetCString = new NativeFunction(Module.findExportByName('CoreFoundation','CFStringGetCString'), 'int8', ['pointer', 'pointer', 'int64', 'int64'])
|
||||
var CFStringGetLength = new NativeFunction(Module.findExportByName('CoreFoundation','CFStringGetLength'), 'int64', ['pointer'])
|
||||
var CFDictionaryGetCount = new NativeFunction(Module.findExportByName('CoreFoundation','CFDictionaryGetCount'), 'int64', ['pointer'])
|
||||
var CFDictionaryGetKeysAndValues = new NativeFunction(Module.findExportByName('CoreFoundation','CFDictionaryGetKeysAndValues'), 'void', ['pointer', 'pointer', 'pointer'])
|
||||
var CFDataGetBytePtr = new NativeFunction(Module.findExportByName('CoreFoundation','CFDataGetBytePtr'), 'pointer', ['pointer'])
|
||||
var CFDataGetLength = new NativeFunction(Module.findExportByName('CoreFoundation','CFDataGetLength'), 'uint64', ['pointer'])
|
||||
|
||||
var readCFStr = (cfs) => {
|
||||
var cfslen = CFStringGetLength(cfs)
|
||||
var cfsBuf = Memory.alloc(cfslen + 1)
|
||||
CFStringGetCString(cfs, cfsBuf, cfslen + 1, 134217984)
|
||||
return Memory.readUtf8String(cfsBuf, cfslen)
|
||||
}
|
||||
|
||||
var readCFDict = (cfdict) => {
|
||||
var dictCount = CFDictionaryGetCount(cfdict)
|
||||
var dictKeys = Memory.alloc(dictCount * 8)
|
||||
var dictValues = Memory.alloc(dictCount * 8)
|
||||
CFDictionaryGetKeysAndValues(cfdict, dictKeys, dictValues)
|
||||
var ret = {}
|
||||
for (var i = 0; i < dictCount; i++) {
|
||||
var k = readCFStr(dictKeys.add(8 * i).readPointer())
|
||||
var v = readCFStr(dictValues.add(8 * i).readPointer())
|
||||
ret[k] = v
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
var readCFData = (cfd) => {
|
||||
var cfdlen = CFDataGetLength(cfd)
|
||||
var cfdbuf = CFDataGetBytePtr(cfd)
|
||||
return cfdbuf.readByteArray(cfdlen)
|
||||
}
|
||||
|
||||
var itunesBase = Process.enumerateModulesSync()[0].base
|
||||
var cfAllocator = itunesBase.add(0x22A8448).readPointer()
|
||||
var kbsyncContext = itunesBase.add(0x22A6BBC).readU32()
|
||||
var prepareAppleHdrWrap = new NativeFunction(itunesBase.add(0x87FFC0), 'pointer',['pointer','pointer','pointer']);
|
||||
var get_cookie_val = new NativeFunction(itunesBase.add(0xBDE500), 'pointer',['pointer']);
|
||||
var get_kbsync = new NativeFunction(itunesBase.add(0x74D210), 'pointer',['uint32', 'uint32', 'pointer']);
|
||||
|
||||
getHeader = function (url) {
|
||||
var GlobalContext = itunesBase.add(0x22A9B18).readPointer()
|
||||
var otpGlobalContext = GlobalContext
|
||||
if (!GlobalContext.isNull()) {
|
||||
otpGlobalContext = GlobalContext.add(62716).readPointer()
|
||||
}
|
||||
|
||||
var otpContext = Memory.alloc(128)
|
||||
otpContext.writePointer(otpGlobalContext)
|
||||
otpContext.add(8).writeU64(0)
|
||||
otpContext.add(16).writeU64(0)
|
||||
otpContext.add(24).writeU16(1)
|
||||
otpContext.add(26).writeU8(0)
|
||||
otpContext.add(27).writeU8(1) // include X-Guid
|
||||
otpContext.add(28).writeU8(1) // include ADIV1 Hdrs
|
||||
otpContext.add(32).writeU32(0)
|
||||
otpContext.add(36).writeU16(0)
|
||||
otpContext.add(40).writeU32(0)
|
||||
otpContext.add(48).writeU64(0)
|
||||
otpContext.add(64).writeU64(0)
|
||||
otpContext.add(72).writeU64(0)
|
||||
otpContext.add(84).writeU64(0)
|
||||
otpContext.add(112).writeU8(1)
|
||||
|
||||
var urlBuf = Memory.allocUtf8String(url)
|
||||
var urlData = CFURLCreateWithBytes(cfAllocator, urlBuf, url.length, 0x8000100, 0)
|
||||
|
||||
var kbsync = get_kbsync(kbsyncContext, 1, otpGlobalContext)
|
||||
|
||||
var cookieCFStr = get_cookie_val(urlData)
|
||||
var hdrDict = prepareAppleHdrWrap(NULL, urlData, otpContext)
|
||||
//hdrdesc = CFCopyDescription(hdrDict)
|
||||
//console.log(readCFStr(hdrdesc))
|
||||
|
||||
var cookieStr = readCFStr(cookieCFStr)
|
||||
var hdrOutput = readCFDict(hdrDict)
|
||||
hdrOutput['Cookie'] = cookieStr
|
||||
|
||||
var kbSyncData = readCFData(kbsync)
|
||||
hdrOutput['kbsync'] = [...new Uint8Array(kbSyncData)].map(x => x.toString(16).padStart(2, '0')).join('');
|
||||
|
||||
return hdrOutput
|
||||
};
|
||||
}
|
||||
|
||||
rpc.exports = {
|
||||
getHeader: (url) => {
|
||||
if (!getHeader) {
|
||||
init()
|
||||
}
|
||||
return getHeader(url);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
cd %~dp0
|
||||
|
||||
curl -LO https://secure-appldnld.apple.com/itunes12/091-87819-20180912-69177170-B085-11E8-B6AB-C1D03409AD2A6/iTunes64Setup.exe
|
||||
iTunes64Setup.exe /extract
|
||||
|
||||
@REM start /wait msiexec.exe /i AppleApplicationSupport.msi /qn
|
||||
start /wait msiexec.exe /i AppleApplicationSupport64.msi /qn
|
||||
@REM start /wait msiexec.exe /i AppleMobileDeviceSupport64.msi /qn
|
||||
@REM start /wait msiexec.exe /i AppleSoftwareUpdate.msi /qn
|
||||
@REM start /wait msiexec.exe /i Bonjour64.msi /qn
|
||||
start /wait msiexec.exe /i iTunes64.msi /qn
|
||||
|
||||
python3 patch_itunes.py
|
||||
22
src_win/actions-iTunes-header/workflow_helper/iTunesInstall/patch_itunes.py
Executable file
22
src_win/actions-iTunes-header/workflow_helper/iTunesInstall/patch_itunes.py
Executable file
@@ -0,0 +1,22 @@
|
||||
import os
|
||||
|
||||
# for debug
|
||||
P = r"C:\Program Files\iTunes\iTunes1.exe"
|
||||
if not os.path.exists(P):
|
||||
# for production
|
||||
P = r"C:\Program Files\iTunes\iTunes.exe"
|
||||
|
||||
with open(P, 'rb') as f:
|
||||
data = f.read()
|
||||
|
||||
data = bytearray(data)
|
||||
|
||||
# Patch passwordSettings (actually useless)
|
||||
data[0x77daf4:0x77daf4+5] = b'\xBF\x03\x00\x00\x00'
|
||||
data[0x77db7e:0x77db7e+2] = b'\xEB\x0A'
|
||||
|
||||
# Patch signIn reason to serverDialog
|
||||
data[0x7a9ed4:0x7a9ed4+6] = b'\xB9\x23\xFF\xFF\xFF\x90'
|
||||
|
||||
with open(P, 'wb') as f:
|
||||
f.write(data)
|
||||
156
src_win/actions-iTunes-header/workflow_helper/itunes_auto_login.py
Executable file
156
src_win/actions-iTunes-header/workflow_helper/itunes_auto_login.py
Executable file
@@ -0,0 +1,156 @@
|
||||
import subprocess
|
||||
import time
|
||||
from pywinauto.application import Application
|
||||
from win32con import *
|
||||
import sys
|
||||
|
||||
ACCOUNT = sys.argv[1]
|
||||
PASSWORD = sys.argv[2]
|
||||
|
||||
print("Launching iTunes...")
|
||||
|
||||
def initITunes():
|
||||
subprocess.call('taskkill /f /im iTunes*', shell=True)
|
||||
|
||||
app = Application().start(r"C:\Program Files\iTunes\iTunes.exe")
|
||||
app.wait_cpu_usage_lower()
|
||||
time.sleep(8)
|
||||
|
||||
def debugTopWin():
|
||||
topwin = app.top_window().wait('exists')
|
||||
texts = []
|
||||
texts += topwin.texts()
|
||||
for c in topwin.iter_children():
|
||||
texts += c.texts()
|
||||
print("-- Cur top win: %s, texts: %s" % (topwin, texts))
|
||||
|
||||
def cleanAllDialog():
|
||||
while True:
|
||||
topwin = app.top_window().wait('exists')
|
||||
if 'Dialog' in topwin.class_name():
|
||||
print(" Closing dialog %s" % topwin.window_text())
|
||||
app.top_window().Button0.click()
|
||||
elif 'Tour' in topwin.window_text():
|
||||
print(" Closing Window %s" % topwin.window_text())
|
||||
topwin.close()
|
||||
else:
|
||||
break
|
||||
|
||||
app.wait_cpu_usage_lower()
|
||||
time.sleep(5)
|
||||
|
||||
# Click all first-time dialogs (like License Agreements, missing audios)
|
||||
cleanAllDialog()
|
||||
|
||||
# Calm down a bit before main window operations
|
||||
app.wait_cpu_usage_lower()
|
||||
debugTopWin()
|
||||
|
||||
# Click main window's first-time question ("No thanks" button)
|
||||
try:
|
||||
buttonText = app.iTunes.Button11.wait('ready').window_text()
|
||||
print('Button11 text is: %s' % buttonText)
|
||||
if 'Search' not in buttonText:
|
||||
print("Clicked 'No Thanks' Button!")
|
||||
app.iTunes.Button11.click_input()
|
||||
app.wait_cpu_usage_lower()
|
||||
time.sleep(4)
|
||||
else:
|
||||
raise Exception('stub')
|
||||
except:
|
||||
print("Not founding 'No Thanks' Button, passing on...")
|
||||
|
||||
|
||||
# Start logging in by clicking toolbar menu "Account"
|
||||
print("Clicking Account menu...")
|
||||
app.iTunes.Application.Static3.click()
|
||||
app.wait_cpu_usage_lower()
|
||||
time.sleep(3)
|
||||
|
||||
debugTopWin()
|
||||
|
||||
# Detect whether we have "&S" in popup, which refers to "Sign in"
|
||||
popup = app.PopupMenu
|
||||
if '&S' not in popup.menu().item(1).text():
|
||||
popup.close()
|
||||
raise Exception("Already logged in!")
|
||||
|
||||
print("Signin menu presented, clicking to login!")
|
||||
# not log in
|
||||
popup.menu().item(1).click_input()
|
||||
app.wait_cpu_usage_lower()
|
||||
time.sleep(8)
|
||||
debugTopWin()
|
||||
|
||||
for i in range(15):
|
||||
dialog = app.top_window()
|
||||
dialogWrap = dialog.wait('ready')
|
||||
assert dialogWrap.friendly_class_name() == 'Dialog'
|
||||
time.sleep(1.0)
|
||||
try:
|
||||
if dialogWrap.window_text() == 'iTunes' \
|
||||
and dialog.Edit1.wait('ready').window_text() == 'Apple ID' \
|
||||
and dialog.Edit2.wait('ready').window_text() == 'Password' \
|
||||
and dialog.Button1.wait('exists').window_text() == '&Sign In':
|
||||
break
|
||||
except Exception as e:
|
||||
continue
|
||||
else:
|
||||
raise Exception("Failed to find login window in 15 iterations!")
|
||||
app.wait_cpu_usage_lower()
|
||||
|
||||
print("Setting login dialog edit texts")
|
||||
|
||||
appleid_Edit = dialog.Edit1
|
||||
appleid_Edit.wait('ready')
|
||||
appleid_Edit.click_input()
|
||||
appleid_Edit.type_keys(ACCOUNT)
|
||||
appleid_Edit.set_edit_text(ACCOUNT)
|
||||
time.sleep(3)
|
||||
|
||||
pass_Edit = dialog.Edit2
|
||||
pass_Edit.wait('ready')
|
||||
pass_Edit.click_input()
|
||||
pass_Edit.type_keys(PASSWORD)
|
||||
pass_Edit.set_edit_text(PASSWORD)
|
||||
time.sleep(3)
|
||||
|
||||
print("Clicking login button!")
|
||||
loginButton = dialog.Button1
|
||||
loginButton.wait('ready')
|
||||
# click multiple times as pywinauto seems to have some bug
|
||||
loginButton.click()
|
||||
time.sleep(0.5)
|
||||
try:
|
||||
loginButton.click()
|
||||
time.sleep(0.5)
|
||||
loginButton.click_input()
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
print("Waiting login result...")
|
||||
time.sleep(10)
|
||||
debugTopWin()
|
||||
|
||||
if app.top_window().handle == dialogWrap.handle:
|
||||
raise Exception("Failed to trigger Login button!")
|
||||
elif app.top_window().window_text() == 'Verification Failed':
|
||||
raise Exception("Verification Failed: %s" % app.top_window().Static2.window_text())
|
||||
|
||||
|
||||
# Finish & Cleanup
|
||||
print("Waiting all dialogs to finish")
|
||||
cleanAllDialog()
|
||||
|
||||
|
||||
for init_i in range(3):
|
||||
try:
|
||||
initITunes()
|
||||
break
|
||||
except Exception as e:
|
||||
print("Init iTunes %d: Failed with %s" % (init_i, e))
|
||||
import traceback; traceback.print_exc()
|
||||
time.sleep(8)
|
||||
|
||||
print("Init iTunes Successfully!")
|
||||
2
src_win/libimobiledevice/README.md
Executable file
2
src_win/libimobiledevice/README.md
Executable file
@@ -0,0 +1,2 @@
|
||||
Libimobiledevice compiled for Windows
|
||||
Updated 18/05/2020. Compiled by iFred09
|
||||
BIN
src_win/libimobiledevice/idevice_id.exe
Executable file
BIN
src_win/libimobiledevice/idevice_id.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/ideviceactivation.exe
Executable file
BIN
src_win/libimobiledevice/ideviceactivation.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/idevicebackup.exe
Executable file
BIN
src_win/libimobiledevice/idevicebackup.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/idevicebackup2.exe
Executable file
BIN
src_win/libimobiledevice/idevicebackup2.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/idevicecrashreport.exe
Executable file
BIN
src_win/libimobiledevice/idevicecrashreport.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/idevicedate.exe
Executable file
BIN
src_win/libimobiledevice/idevicedate.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/idevicedebug.exe
Executable file
BIN
src_win/libimobiledevice/idevicedebug.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/idevicedebugserverproxy.exe
Executable file
BIN
src_win/libimobiledevice/idevicedebugserverproxy.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/idevicediagnostics.exe
Executable file
BIN
src_win/libimobiledevice/idevicediagnostics.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/ideviceenterrecovery.exe
Executable file
BIN
src_win/libimobiledevice/ideviceenterrecovery.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/ideviceimagemounter.exe
Executable file
BIN
src_win/libimobiledevice/ideviceimagemounter.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/ideviceinfo.exe
Executable file
BIN
src_win/libimobiledevice/ideviceinfo.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/ideviceinstaller.exe
Executable file
BIN
src_win/libimobiledevice/ideviceinstaller.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/idevicename.exe
Executable file
BIN
src_win/libimobiledevice/idevicename.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/idevicenotificationproxy.exe
Executable file
BIN
src_win/libimobiledevice/idevicenotificationproxy.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/idevicepair.exe
Executable file
BIN
src_win/libimobiledevice/idevicepair.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/ideviceprovision.exe
Executable file
BIN
src_win/libimobiledevice/ideviceprovision.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/idevicerestore.exe
Executable file
BIN
src_win/libimobiledevice/idevicerestore.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/idevicescreenshot.exe
Executable file
BIN
src_win/libimobiledevice/idevicescreenshot.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/idevicesetlocation.exe
Executable file
BIN
src_win/libimobiledevice/idevicesetlocation.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/idevicesyslog.exe
Executable file
BIN
src_win/libimobiledevice/idevicesyslog.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/inetcat.exe
Executable file
BIN
src_win/libimobiledevice/inetcat.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/iproxy.exe
Executable file
BIN
src_win/libimobiledevice/iproxy.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/irecovery.exe
Executable file
BIN
src_win/libimobiledevice/irecovery.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libbrotlicommon.dll
Executable file
BIN
src_win/libimobiledevice/libbrotlicommon.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libbrotlidec.dll
Executable file
BIN
src_win/libimobiledevice/libbrotlidec.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libbz2-1.dll
Executable file
BIN
src_win/libimobiledevice/libbz2-1.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libcrypto-1_1.dll
Executable file
BIN
src_win/libimobiledevice/libcrypto-1_1.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libcurl-4.dll
Executable file
BIN
src_win/libimobiledevice/libcurl-4.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libeay32.dll
Executable file
BIN
src_win/libimobiledevice/libeay32.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libffi-6.dll
Executable file
BIN
src_win/libimobiledevice/libffi-6.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libgcc_s_dw2-1.dll
Executable file
BIN
src_win/libimobiledevice/libgcc_s_dw2-1.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libgmp-10.dll
Executable file
BIN
src_win/libimobiledevice/libgmp-10.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libgnutls-30.dll
Executable file
BIN
src_win/libimobiledevice/libgnutls-30.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libhogweed-4-2.dll
Executable file
BIN
src_win/libimobiledevice/libhogweed-4-2.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libhogweed-4.dll
Executable file
BIN
src_win/libimobiledevice/libhogweed-4.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libiconv-2.dll
Executable file
BIN
src_win/libimobiledevice/libiconv-2.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libideviceactivation-2.dll
Executable file
BIN
src_win/libimobiledevice/libideviceactivation-2.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libideviceactivation.dll
Executable file
BIN
src_win/libimobiledevice/libideviceactivation.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libidn-11.dll
Executable file
BIN
src_win/libimobiledevice/libidn-11.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libidn2-0.dll
Executable file
BIN
src_win/libimobiledevice/libidn2-0.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libimobiledevice.dll
Executable file
BIN
src_win/libimobiledevice/libimobiledevice.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libintl-8.dll
Executable file
BIN
src_win/libimobiledevice/libintl-8.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libirecovery.dll
Executable file
BIN
src_win/libimobiledevice/libirecovery.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/liblzma-5.dll
Executable file
BIN
src_win/libimobiledevice/liblzma-5.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libnettle-6-2.dll
Executable file
BIN
src_win/libimobiledevice/libnettle-6-2.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libnettle-6.dll
Executable file
BIN
src_win/libimobiledevice/libnettle-6.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libnghttp2-14.dll
Executable file
BIN
src_win/libimobiledevice/libnghttp2-14.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libp11-kit-0.dll
Executable file
BIN
src_win/libimobiledevice/libp11-kit-0.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libplist++-3.dll
Executable file
BIN
src_win/libimobiledevice/libplist++-3.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libplist++.dll
Executable file
BIN
src_win/libimobiledevice/libplist++.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libplist.dll
Executable file
BIN
src_win/libimobiledevice/libplist.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libpsl-5.dll
Executable file
BIN
src_win/libimobiledevice/libpsl-5.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libreadline6.dll
Executable file
BIN
src_win/libimobiledevice/libreadline6.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libreadline8.dll
Executable file
BIN
src_win/libimobiledevice/libreadline8.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/librtmp-1.dll
Executable file
BIN
src_win/libimobiledevice/librtmp-1.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libssh2-1.dll
Executable file
BIN
src_win/libimobiledevice/libssh2-1.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libssl-1_1.dll
Executable file
BIN
src_win/libimobiledevice/libssl-1_1.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libtasn1-6.dll
Executable file
BIN
src_win/libimobiledevice/libtasn1-6.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libtermcap-0.dll
Executable file
BIN
src_win/libimobiledevice/libtermcap-0.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libunistring-2.dll
Executable file
BIN
src_win/libimobiledevice/libunistring-2.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libusbmuxd.dll
Executable file
BIN
src_win/libimobiledevice/libusbmuxd.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libwinpthread-1.dll
Executable file
BIN
src_win/libimobiledevice/libwinpthread-1.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libxml2-2.dll
Executable file
BIN
src_win/libimobiledevice/libxml2-2.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libzip-4.dll
Executable file
BIN
src_win/libimobiledevice/libzip-4.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/libzip.dll
Executable file
BIN
src_win/libimobiledevice/libzip.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/plistutil.exe
Executable file
BIN
src_win/libimobiledevice/plistutil.exe
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/ssleay32.dll
Executable file
BIN
src_win/libimobiledevice/ssleay32.dll
Executable file
Binary file not shown.
BIN
src_win/libimobiledevice/zlib1.dll
Executable file
BIN
src_win/libimobiledevice/zlib1.dll
Executable file
Binary file not shown.
0
src_win/queued/place_ipas_here.txt
Normal file
0
src_win/queued/place_ipas_here.txt
Normal file
54
src_win/win_server.py
Executable file
54
src_win/win_server.py
Executable file
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python3
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
from pathlib import Path
|
||||
import os
|
||||
import socket
|
||||
import subprocess
|
||||
|
||||
os.chdir(Path(__file__).parent)
|
||||
INSTALLER = Path('libimobiledevice', 'ideviceinstaller.exe')
|
||||
PATH_IN = Path('queued')
|
||||
|
||||
|
||||
class IpaServer(BaseHTTPRequestHandler):
|
||||
def reply(self, status: int, data: str):
|
||||
self.send_response(status)
|
||||
self.send_header('Access-Control-Allow-Origin', '*')
|
||||
self.send_header('Content-type', 'text/plain')
|
||||
self.end_headers()
|
||||
self.wfile.write(data.encode('utf8'))
|
||||
|
||||
def do_POST(self):
|
||||
length = self.headers.get('Content-Length', 1)
|
||||
data = self.rfile.read(int(length)).decode('utf8')
|
||||
if self.path == '/up':
|
||||
return self.reply(200, 'YES')
|
||||
elif self.path == '/install':
|
||||
fname = PATH_IN / data
|
||||
if not fname.exists():
|
||||
return self.reply(404, f'File not found "{fname}"')
|
||||
subprocess.run([INSTALLER, '-i', fname])
|
||||
elif self.path == '/uninstall':
|
||||
bundleId = data
|
||||
subprocess.run([INSTALLER, '-U', bundleId], timeout=60)
|
||||
else:
|
||||
raise ValueError('unsuppoted API path')
|
||||
return self.reply(200, 'OK')
|
||||
|
||||
|
||||
def getLocalIp():
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.connect(('10.255.255.255', 80))
|
||||
ip = s.getsockname()[0]
|
||||
s.close()
|
||||
return ip
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
webServer = HTTPServer(('0.0.0.0', 8117), IpaServer)
|
||||
print('Server started http://%s:%s' % (getLocalIp(), 8117))
|
||||
try:
|
||||
webServer.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
webServer.server_close()
|
||||
Reference in New Issue
Block a user