├── .DS_Store
├── .gitignore
├── LICENSE
├── README.md
├── lib
├── unidbg-android-0.7.0.jar
└── unidbg-api-0.7.0.jar
├── log
├── .DS_Store
├── logs.log
├── logs_2022-03-06.log
└── logs_2022-04-10.log
├── mvnw
├── mvnw.cmd
├── pom.xml
├── src
├── .DS_Store
├── main
│ ├── .DS_Store
│ ├── java
│ │ ├── .DS_Store
│ │ └── com
│ │ │ ├── .DS_Store
│ │ │ └── douyin
│ │ │ ├── .DS_Store
│ │ │ └── spider
│ │ │ ├── DouyinSpiderApplication.java
│ │ │ ├── controller
│ │ │ └── DouyinController.java
│ │ │ ├── jni
│ │ │ ├── JniDispatchRegister.java
│ │ │ └── JniDispatchXGorgon.java
│ │ │ ├── service
│ │ │ ├── RegisterService.java
│ │ │ └── XGorgonService.java
│ │ │ └── util
│ │ │ ├── DouYinRegisterInfo.java
│ │ │ └── URLUtil.java
│ └── resources
│ │ ├── .DS_Store
│ │ ├── application.properties
│ │ ├── dylib
│ │ ├── libEncryptor.so
│ │ ├── libcms.so
│ │ └── libttEncrypt.so
│ │ └── log4j2.xml
└── test
│ ├── .DS_Store
│ └── java
│ ├── .DS_Store
│ └── com
│ ├── .DS_Store
│ └── douyin
│ ├── .DS_Store
│ └── spider
│ └── DouyinSpiderApplicationTests.java
└── target
├── .DS_Store
├── classes
├── application.properties
├── com
│ └── douyin
│ │ └── spider
│ │ ├── DouyinSpiderApplication.class
│ │ ├── controller
│ │ └── DouyinController.class
│ │ ├── jni
│ │ ├── JniDispatchRegister.class
│ │ └── JniDispatchXGorgon.class
│ │ ├── service
│ │ ├── RegisterService.class
│ │ └── XGorgonService.class
│ │ └── util
│ │ ├── DouYinRegisterInfo.class
│ │ └── URLUtil.class
├── dylib
│ ├── libEncryptor.so
│ ├── libcms.so
│ └── libttEncrypt.so
└── log4j2.xml
├── douyin-spider-0.0.1-SNAPSHOT.jar
├── douyin-spider-0.0.1-SNAPSHOT.jar.original
├── log
├── logs.log
└── logs_2021-11-11.log
├── maven-archiver
└── pom.properties
├── maven-status
└── maven-compiler-plugin
│ ├── compile
│ └── default-compile
│ │ ├── createdFiles.lst
│ │ └── inputFiles.lst
│ └── testCompile
│ └── default-testCompile
│ ├── createdFiles.lst
│ └── inputFiles.lst
├── rootfs
└── default
│ ├── dev
│ └── log
│ │ ├── events
│ │ ├── main
│ │ ├── radio
│ │ └── system
│ ├── stderr.txt
│ └── stdout.txt
├── target
└── rootfs
│ └── default
│ ├── dev
│ └── log
│ │ ├── events
│ │ ├── main
│ │ ├── radio
│ │ └── system
│ ├── stderr.txt
│ └── stdout.txt
└── test-classes
└── com
└── douyin
└── spider
└── DouyinSpiderApplicationTests.class
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RipperTs/tiktok-device-registration/08efa14c21ed8139b695005f821ff282e0b0e1e6/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | ### IntelliJ IDEA ###
3 | .idea
4 |
5 |
6 | ### VS Code ###
7 | .vscode/
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Ripper
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 部署文档
2 |
3 | > 基于抖音版本12.5.0 so文件
4 |
5 | #### 依赖环境
6 |
7 | Java 1.8 Maven
8 |
9 | ##### 安装 Maven
10 |
11 | ```
12 | wget http://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz
13 | ```
14 |
15 | ````
16 | tar -zxvf apache-maven-3.3.9-bin.tar.gz
17 | ````
18 |
19 | ````
20 | mv apache-maven-3.3.9 /usr/local/maven
21 | ````
22 |
23 | ````
24 | vim /etc/profile
25 | ````
26 |
27 | 在/etc/profile文件末尾增加以下配置:
28 |
29 | ````
30 | M2_HOME=/usr/local/maven
31 | export PATH=${M2_HOME}/bin:${PATH}
32 | ````
33 |
34 | 重载/etc/profile这个文件
35 |
36 | ````
37 | source /etc/profile
38 | ````
39 |
40 | 检查安装
41 |
42 | ```
43 | mvn -v
44 | ```
45 |
46 |
47 |
48 | ### 一键代码Jar包
49 |
50 | ```
51 | cd 目录
52 | ```
53 | ```
54 | mvn clean install -DskipTests
55 | ```
56 | ```
57 | cd target
58 | ```
59 | ```
60 | java -jar douyin-spider-0.0.1-SNAPSHOT.jar
61 | ```
62 | ---
63 | 访问地址: http://localhost:8022/register
64 |
65 | ---
66 |
67 | ### 注意
68 |
69 | 服务器需要开9022端口。
70 |
71 | 跑脚本需要间隔3秒,否则可能出现抖音风控
72 |
73 | ##### 其他
74 | 清理nohup.out 日志
75 | ```
76 | cat /dev/null > /www/wwwroot/douyin-register-spider/target/nohup.out
77 | ```
78 |
79 | 此代码仅供学习参考,设备信息版本太老,利用率很低的.
80 | 如果访问接口出现3072表示还需要滑块验证
81 |
82 | #### 常见问题
83 |
84 | 如果注册出来的大批量设备无法使用(获取不到数据),可以尝试使用真机设备标识. 如果还是不行说明接口风控升级了,需要新版的算法
85 |
--------------------------------------------------------------------------------
/lib/unidbg-android-0.7.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RipperTs/tiktok-device-registration/08efa14c21ed8139b695005f821ff282e0b0e1e6/lib/unidbg-android-0.7.0.jar
--------------------------------------------------------------------------------
/lib/unidbg-api-0.7.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RipperTs/tiktok-device-registration/08efa14c21ed8139b695005f821ff282e0b0e1e6/lib/unidbg-api-0.7.0.jar
--------------------------------------------------------------------------------
/log/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RipperTs/tiktok-device-registration/08efa14c21ed8139b695005f821ff282e0b0e1e6/log/.DS_Store
--------------------------------------------------------------------------------
/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # https://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /etc/mavenrc ] ; then
40 | . /etc/mavenrc
41 | fi
42 |
43 | if [ -f "$HOME/.mavenrc" ] ; then
44 | . "$HOME/.mavenrc"
45 | fi
46 |
47 | fi
48 |
49 | # OS specific support. $var _must_ be set to either true or false.
50 | cygwin=false;
51 | darwin=false;
52 | mingw=false
53 | case "`uname`" in
54 | CYGWIN*) cygwin=true ;;
55 | MINGW*) mingw=true;;
56 | Darwin*) darwin=true
57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
59 | if [ -z "$JAVA_HOME" ]; then
60 | if [ -x "/usr/libexec/java_home" ]; then
61 | export JAVA_HOME="`/usr/libexec/java_home`"
62 | else
63 | export JAVA_HOME="/Library/Java/Home"
64 | fi
65 | fi
66 | ;;
67 | esac
68 |
69 | if [ -z "$JAVA_HOME" ] ; then
70 | if [ -r /etc/gentoo-release ] ; then
71 | JAVA_HOME=`java-config --jre-home`
72 | fi
73 | fi
74 |
75 | if [ -z "$M2_HOME" ] ; then
76 | ## resolve links - $0 may be a link to maven's home
77 | PRG="$0"
78 |
79 | # need this for relative symlinks
80 | while [ -h "$PRG" ] ; do
81 | ls=`ls -ld "$PRG"`
82 | link=`expr "$ls" : '.*-> \(.*\)$'`
83 | if expr "$link" : '/.*' > /dev/null; then
84 | PRG="$link"
85 | else
86 | PRG="`dirname "$PRG"`/$link"
87 | fi
88 | done
89 |
90 | saveddir=`pwd`
91 |
92 | M2_HOME=`dirname "$PRG"`/..
93 |
94 | # make it fully qualified
95 | M2_HOME=`cd "$M2_HOME" && pwd`
96 |
97 | cd "$saveddir"
98 | # echo Using m2 at $M2_HOME
99 | fi
100 |
101 | # For Cygwin, ensure paths are in UNIX format before anything is touched
102 | if $cygwin ; then
103 | [ -n "$M2_HOME" ] &&
104 | M2_HOME=`cygpath --unix "$M2_HOME"`
105 | [ -n "$JAVA_HOME" ] &&
106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
107 | [ -n "$CLASSPATH" ] &&
108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
109 | fi
110 |
111 | # For Mingw, ensure paths are in UNIX format before anything is touched
112 | if $mingw ; then
113 | [ -n "$M2_HOME" ] &&
114 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
115 | [ -n "$JAVA_HOME" ] &&
116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
117 | fi
118 |
119 | if [ -z "$JAVA_HOME" ]; then
120 | javaExecutable="`which javac`"
121 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
122 | # readlink(1) is not available as standard on Solaris 10.
123 | readLink=`which readlink`
124 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
125 | if $darwin ; then
126 | javaHome="`dirname \"$javaExecutable\"`"
127 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
128 | else
129 | javaExecutable="`readlink -f \"$javaExecutable\"`"
130 | fi
131 | javaHome="`dirname \"$javaExecutable\"`"
132 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
133 | JAVA_HOME="$javaHome"
134 | export JAVA_HOME
135 | fi
136 | fi
137 | fi
138 |
139 | if [ -z "$JAVACMD" ] ; then
140 | if [ -n "$JAVA_HOME" ] ; then
141 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
142 | # IBM's JDK on AIX uses strange locations for the executables
143 | JAVACMD="$JAVA_HOME/jre/sh/java"
144 | else
145 | JAVACMD="$JAVA_HOME/bin/java"
146 | fi
147 | else
148 | JAVACMD="`which java`"
149 | fi
150 | fi
151 |
152 | if [ ! -x "$JAVACMD" ] ; then
153 | echo "Error: JAVA_HOME is not defined correctly." >&2
154 | echo " We cannot execute $JAVACMD" >&2
155 | exit 1
156 | fi
157 |
158 | if [ -z "$JAVA_HOME" ] ; then
159 | echo "Warning: JAVA_HOME environment variable is not set."
160 | fi
161 |
162 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
163 |
164 | # traverses directory structure from process work directory to filesystem root
165 | # first directory with .mvn subdirectory is considered project base directory
166 | find_maven_basedir() {
167 |
168 | if [ -z "$1" ]
169 | then
170 | echo "Path not specified to find_maven_basedir"
171 | return 1
172 | fi
173 |
174 | basedir="$1"
175 | wdir="$1"
176 | while [ "$wdir" != '/' ] ; do
177 | if [ -d "$wdir"/.mvn ] ; then
178 | basedir=$wdir
179 | break
180 | fi
181 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
182 | if [ -d "${wdir}" ]; then
183 | wdir=`cd "$wdir/.."; pwd`
184 | fi
185 | # end of workaround
186 | done
187 | echo "${basedir}"
188 | }
189 |
190 | # concatenates all lines of a file
191 | concat_lines() {
192 | if [ -f "$1" ]; then
193 | echo "$(tr -s '\n' ' ' < "$1")"
194 | fi
195 | }
196 |
197 | BASE_DIR=`find_maven_basedir "$(pwd)"`
198 | if [ -z "$BASE_DIR" ]; then
199 | exit 1;
200 | fi
201 |
202 | ##########################################################################################
203 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
204 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
205 | ##########################################################################################
206 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
207 | if [ "$MVNW_VERBOSE" = true ]; then
208 | echo "Found .mvn/wrapper/maven-wrapper.jar"
209 | fi
210 | else
211 | if [ "$MVNW_VERBOSE" = true ]; then
212 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
213 | fi
214 | if [ -n "$MVNW_REPOURL" ]; then
215 | jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
216 | else
217 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
218 | fi
219 | while IFS="=" read key value; do
220 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
221 | esac
222 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
223 | if [ "$MVNW_VERBOSE" = true ]; then
224 | echo "Downloading from: $jarUrl"
225 | fi
226 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
227 | if $cygwin; then
228 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
229 | fi
230 |
231 | if command -v wget > /dev/null; then
232 | if [ "$MVNW_VERBOSE" = true ]; then
233 | echo "Found wget ... using wget"
234 | fi
235 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
236 | wget "$jarUrl" -O "$wrapperJarPath"
237 | else
238 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
239 | fi
240 | elif command -v curl > /dev/null; then
241 | if [ "$MVNW_VERBOSE" = true ]; then
242 | echo "Found curl ... using curl"
243 | fi
244 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
245 | curl -o "$wrapperJarPath" "$jarUrl" -f
246 | else
247 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
248 | fi
249 |
250 | else
251 | if [ "$MVNW_VERBOSE" = true ]; then
252 | echo "Falling back to using Java to download"
253 | fi
254 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
255 | # For Cygwin, switch paths to Windows format before running javac
256 | if $cygwin; then
257 | javaClass=`cygpath --path --windows "$javaClass"`
258 | fi
259 | if [ -e "$javaClass" ]; then
260 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
261 | if [ "$MVNW_VERBOSE" = true ]; then
262 | echo " - Compiling MavenWrapperDownloader.java ..."
263 | fi
264 | # Compiling the Java class
265 | ("$JAVA_HOME/bin/javac" "$javaClass")
266 | fi
267 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
268 | # Running the downloader
269 | if [ "$MVNW_VERBOSE" = true ]; then
270 | echo " - Running MavenWrapperDownloader.java ..."
271 | fi
272 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
273 | fi
274 | fi
275 | fi
276 | fi
277 | ##########################################################################################
278 | # End of extension
279 | ##########################################################################################
280 |
281 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
282 | if [ "$MVNW_VERBOSE" = true ]; then
283 | echo $MAVEN_PROJECTBASEDIR
284 | fi
285 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
286 |
287 | # For Cygwin, switch paths to Windows format before running java
288 | if $cygwin; then
289 | [ -n "$M2_HOME" ] &&
290 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
291 | [ -n "$JAVA_HOME" ] &&
292 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
293 | [ -n "$CLASSPATH" ] &&
294 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
295 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
296 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
297 | fi
298 |
299 | # Provide a "standardized" way to retrieve the CLI args that will
300 | # work with both Windows and non-Windows executions.
301 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
302 | export MAVEN_CMD_LINE_ARGS
303 |
304 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
305 |
306 | exec "$JAVACMD" \
307 | $MAVEN_OPTS \
308 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
309 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
310 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
311 |
--------------------------------------------------------------------------------
/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
124 |
125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
127 | )
128 |
129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
131 | if exist %WRAPPER_JAR% (
132 | if "%MVNW_VERBOSE%" == "true" (
133 | echo Found %WRAPPER_JAR%
134 | )
135 | ) else (
136 | if not "%MVNW_REPOURL%" == "" (
137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
138 | )
139 | if "%MVNW_VERBOSE%" == "true" (
140 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
141 | echo Downloading from: %DOWNLOAD_URL%
142 | )
143 |
144 | powershell -Command "&{"^
145 | "$webclient = new-object System.Net.WebClient;"^
146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
148 | "}"^
149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
150 | "}"
151 | if "%MVNW_VERBOSE%" == "true" (
152 | echo Finished downloading %WRAPPER_JAR%
153 | )
154 | )
155 | @REM End of extension
156 |
157 | @REM Provide a "standardized" way to retrieve the CLI args that will
158 | @REM work with both Windows and non-Windows executions.
159 | set MAVEN_CMD_LINE_ARGS=%*
160 |
161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
162 | if ERRORLEVEL 1 goto error
163 | goto end
164 |
165 | :error
166 | set ERROR_CODE=1
167 |
168 | :end
169 | @endlocal & set ERROR_CODE=%ERROR_CODE%
170 |
171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
175 | :skipRcPost
176 |
177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
179 |
180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
181 |
182 | exit /B %ERROR_CODE%
183 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.3.1.RELEASE
9 |
10 |
11 | com.douyin.spider
12 | douyin-spider
13 | 0.0.1-SNAPSHOT
14 | douyin-spider
15 | Demo project for Spring Boot
16 |
17 |
18 | 1.8
19 |
20 |
21 |
22 |
23 | com.squareup.okhttp3
24 | okhttp
25 | 3.11.0
26 |
27 |
28 | org.json
29 | json
30 | 20190722
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | org.springframework.boot
40 | spring-boot-starter
41 | 2.3.1.RELEASE
42 |
43 |
44 | org.springframework.boot
45 | spring-boot-starter-logging
46 |
47 |
48 |
49 |
50 |
51 | org.springframework.boot
52 | spring-boot-starter-log4j2
53 | 2.3.1.RELEASE
54 |
55 |
56 |
57 | org.springframework.boot
58 | spring-boot-starter-web
59 | 2.3.1.RELEASE
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | net.dongliu
74 | apk-parser
75 | 2.6.4
76 |
77 |
78 |
79 | com.github.zhkl0228
80 | unicorn
81 | 1.0.9
82 |
83 |
84 | com.github.zhkl0228
85 | capstone
86 | 3.0.8
87 |
88 |
89 | com.github.zhkl0228
90 | keystone
91 | 0.9.2
92 |
93 |
94 | commons-codec
95 | commons-codec
96 | 1.6
97 |
98 |
99 | commons-io
100 | commons-io
101 | 2.4
102 |
103 |
104 | commons-logging
105 | commons-logging
106 | 1.1.3
107 |
108 |
109 | com.alibaba
110 | fastjson
111 | 1.2.60
112 |
113 |
114 | com.github.zhkl0228
115 | demumble
116 | 1.0.1
117 |
118 |
119 |
120 | com.github.zhkl0228
121 | unidbg-android
122 | 0.7.0
123 | system
124 | ${project.basedir}/lib/unidbg-android-0.7.0.jar
125 |
126 |
127 |
128 | com.github.zhkl0228
129 | unidbg-api
130 | 0.7.0
131 | system
132 | ${project.basedir}/lib/unidbg-api-0.7.0.jar
133 |
134 |
135 |
136 | org.junit.jupiter
137 | junit-jupiter-api
138 | 5.5.0
139 | test
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 | org.springframework.boot
149 | spring-boot-maven-plugin
150 |
151 | true
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
--------------------------------------------------------------------------------
/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RipperTs/tiktok-device-registration/08efa14c21ed8139b695005f821ff282e0b0e1e6/src/.DS_Store
--------------------------------------------------------------------------------
/src/main/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RipperTs/tiktok-device-registration/08efa14c21ed8139b695005f821ff282e0b0e1e6/src/main/.DS_Store
--------------------------------------------------------------------------------
/src/main/java/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RipperTs/tiktok-device-registration/08efa14c21ed8139b695005f821ff282e0b0e1e6/src/main/java/.DS_Store
--------------------------------------------------------------------------------
/src/main/java/com/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RipperTs/tiktok-device-registration/08efa14c21ed8139b695005f821ff282e0b0e1e6/src/main/java/com/.DS_Store
--------------------------------------------------------------------------------
/src/main/java/com/douyin/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RipperTs/tiktok-device-registration/08efa14c21ed8139b695005f821ff282e0b0e1e6/src/main/java/com/douyin/.DS_Store
--------------------------------------------------------------------------------
/src/main/java/com/douyin/spider/DouyinSpiderApplication.java:
--------------------------------------------------------------------------------
1 | package com.douyin.spider;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class DouyinSpiderApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(DouyinSpiderApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/douyin/spider/controller/DouyinController.java:
--------------------------------------------------------------------------------
1 | package com.douyin.spider.controller;
2 |
3 | import com.douyin.spider.service.RegisterService;
4 | import com.douyin.spider.service.XGorgonService;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.web.bind.annotation.*;
9 |
10 | import java.io.IOException;
11 | import java.util.Map;
12 |
13 | /**
14 | * @description:采集对外接口
15 | * @modified By:wslmf
16 | * @version: $
17 | */
18 | @RestController
19 | public class DouyinController {
20 |
21 | private static Logger logger = LoggerFactory.getLogger(DouyinController.class);
22 |
23 | @Autowired
24 | RegisterService registerService;
25 |
26 | @Autowired
27 | XGorgonService xGorgonService;
28 |
29 | @RequestMapping(value = "register",method = RequestMethod.GET)
30 | @ResponseBody
31 | public Map register() throws IOException {
32 | return registerService.register();
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/com/douyin/spider/jni/JniDispatchRegister.java:
--------------------------------------------------------------------------------
1 | package com.douyin.spider.jni;
2 |
3 | import com.github.unidbg.AndroidEmulator;
4 | import com.github.unidbg.LibraryResolver;
5 | import com.github.unidbg.Module;
6 | import com.github.unidbg.Symbol;
7 | import com.github.unidbg.linux.android.AndroidARMEmulator;
8 | import com.github.unidbg.linux.android.AndroidResolver;
9 | import com.github.unidbg.linux.android.dvm.*;
10 | import com.github.unidbg.linux.android.dvm.array.ByteArray;
11 | import com.github.unidbg.memory.Memory;
12 | import com.github.unidbg.memory.MemoryBlock;
13 | import org.apache.commons.io.FileUtils;
14 | import org.apache.commons.io.IOUtils;
15 | import org.slf4j.Logger;
16 | import org.slf4j.LoggerFactory;
17 | import org.springframework.context.annotation.Configuration;
18 | import org.springframework.core.io.ClassPathResource;
19 |
20 | import java.io.File;
21 | import java.io.IOException;
22 | import java.io.InputStream;
23 |
24 | @Configuration
25 | public class JniDispatchRegister extends AbstractJni {
26 |
27 | private static String soPath = "dylib/libEncryptor.so";
28 | private static String soName = "soName";
29 | private static String className = "com/bytedance/frameworks/encryptor/EncryptorUtil";
30 | private static String methodSign = "ttEncrypt([BI)[B";
31 | private static Logger logger = LoggerFactory.getLogger(JniDispatchRegister.class);
32 | private static LibraryResolver createLibraryResolver() {
33 | return new AndroidResolver(23);
34 | }
35 |
36 | private static AndroidEmulator createARMEmulator() {
37 | return new AndroidARMEmulator("com.sun.jna");
38 | }
39 |
40 | private final AndroidEmulator emulator;
41 | private final Module module;
42 | private final VM vm;
43 |
44 | private final DvmClass Native;
45 |
46 | public JniDispatchRegister(){
47 |
48 | emulator = createARMEmulator();
49 | final Memory memory = emulator.getMemory();
50 | memory.setLibraryResolver(createLibraryResolver());
51 |
52 | vm = emulator.createDalvikVM(null);
53 | vm.setJni(this);
54 | vm.setVerbose(true);
55 | ClassPathResource resource = new ClassPathResource(soPath);
56 | File soFile = null;
57 | InputStream inputStream = null;
58 | try {
59 | inputStream = resource.getInputStream();
60 | File tempFile = File.createTempFile(soName, ".so");
61 | FileUtils.copyInputStreamToFile(inputStream,tempFile);
62 | soFile = tempFile;
63 | } catch (IOException e) {
64 | e.printStackTrace();
65 | }finally {
66 | IOUtils.closeQuietly(inputStream);
67 | }
68 | // File soFile = null;
69 | // try {
70 | // soFile = ResourceUtils.getFile("classpath:" + soPath);
71 | // } catch (FileNotFoundException e) {
72 | // e.printStackTrace();
73 | // }
74 | // File soFile = new File("D:\\CodeWorkSpace\\spiderWorkSpace\\unidbgProject\\unidbg-android\\src\\main\\resources\\dylib\\libEncryptor.so");
75 | DalvikModule dm = vm.loadLibrary(soFile, false);
76 | dm.callJNI_OnLoad(emulator);
77 | this.module = dm.getModule();
78 |
79 | Native = vm.resolveClass(className);
80 |
81 | Symbol __system_property_get = module.findSymbolByName("__system_property_get", true);
82 | MemoryBlock block = memory.malloc(0x10);
83 | Number ret = __system_property_get.call(emulator, "ro.build.version.sdk", block.getPointer())[0];
84 | logger.info("sdk=" + new String(block.getPointer().getByteArray(0, ret.intValue())));
85 | }
86 |
87 | private void destroy() {
88 | try {
89 | emulator.close();
90 | } catch (IOException e) {
91 | e.printStackTrace();
92 | }
93 | }
94 |
95 | public static void main(String[] args) throws Exception {
96 |
97 | JniDispatchRegister test = new JniDispatchRegister();
98 |
99 | test.test();
100 |
101 | test.destroy();
102 | }
103 |
104 | public byte[] callttEncryptMethod(byte[] data){
105 | // Native.callStaticJniMethod(emulator, methodSign, data,data.length);
106 | Object ret = Native.callStaticJniMethodObject(emulator, methodSign, new ByteArray(vm,data),data.length);
107 | byte[] tt = (byte[]) ((DvmObject) ret).getValue();
108 | return tt;
109 | }
110 |
111 | private void test() throws Exception {
112 |
113 | // Map deviceParams = DouYinRegisterInfo.getDeviceParams();
114 | // JSONObject registerInfo = DouYinRegisterInfo.getRegisterInfo(deviceParams);
115 | // byte[] data = compress(registerInfo.toString(),"utf-8");
116 | //// byte[] data = new byte[]{100, 101, 118, 105, 99, 101, 95, 116, 121, 112, 101, 61, 79, 78, 69, 80, 76, 85, 83, 32, 65, 51, 48, 48, 48, 38, 100, 101, 118, 105, 99, 101, 95, 98, 114, 97, 110, 100, 61, 79, 110, 101, 80, 108, 117, 115};
117 | //// int time = (int) (System.currentTimeMillis() / 1000);
118 | // byte[] tt = callttEncryptMethod(data);
119 | //
120 | //// logger.info("string 类型"+ Arrays.toString(tt));
121 | //// logger.info("byte 【"+ Arrays.toString((byte[]) ((DvmObject) ret).getValue()));
122 | // String resp = sendPost(deviceParams, tt);
123 | // JSONObject jsonObject = new JSONObject(resp);
124 | //
125 | // Map stringObjectMap = registerInfo.getJSONObject("header").toMap();
126 | // Map device_message = jsonObject.toMap();
127 | // for(String key :device_message.keySet()){
128 | // if(key.equals("install_id_str")){
129 | // stringObjectMap.put("iid",device_message.get(key));
130 | // }
131 | // stringObjectMap.put(key,device_message.get(key));
132 | // }
133 | // deviceParams.putAll(stringObjectMap);
134 | // deviceParams.put("uuid",deviceParams.get("udid"));
135 | // logger.info("【device param 】"+new JSONObject(deviceParams));
136 | //
137 | // deviceParams.put("sim_serial_number","89860042191573218601");
138 | // // 激活
139 | //// app_alert(deviceParams);
140 | // // 调用列表数据
141 | // String url ="https://aweme.snssdk.com/aweme/v1/aweme/post/?source=0&max_cursor=0&sec_user_id=MS4wLjABAAAAryNwJa_HtclngdC-xXIKvG8liaveo5h4kiOjIBt5I1ml76MM-WRniwqzWDIZREl9&count=20&os_api=23&device_type=ONEPLUS%20A3000&ssmix=a&manifest_version_code=110500&dpi=480&uuid=863581039914077&app_name=douyin_lite&version_name=11.5.0&ts=1600745725&app_type=normal&ac=wifi&update_version_code=11509900&channel=oppo&_rticket=1600745727371&device_platform=android&iid=3518051136579950&version_code=110500&mac_address=C0%3AEE%3AFB%3AE0%3A31%3A89&cdid=dfd60f13-53ca-42eb-8af9-d187f5ca2edc&openudid=a9fc3bd6e5c99814&device_id=39796983352&resolution=1080*1920&os_version=6.0.1&language=zh&device_brand=OnePlus&aid=2329";
142 | // url = URLUtil.replaceParam(url, deviceParams);
143 | // XgorgonService xgorgonService = new XgorgonService();
144 | // Map map = xgorgonService.generateXGorgon(url);
145 | // XgorgonService.getVideoList(url,map.get("X-Gorgon").toString(),map.get("X-Khronos").toString());
146 | //
147 |
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/src/main/java/com/douyin/spider/jni/JniDispatchXGorgon.java:
--------------------------------------------------------------------------------
1 | package com.douyin.spider.jni;
2 |
3 | import com.github.unidbg.*;
4 | import com.github.unidbg.Module;
5 | import com.github.unidbg.linux.android.*;
6 | import com.github.unidbg.linux.android.dvm.*;
7 | import com.github.unidbg.linux.android.dvm.array.ByteArray;
8 | import com.github.unidbg.memory.Memory;
9 | import com.github.unidbg.memory.MemoryBlock;
10 |
11 | import org.apache.commons.io.FileUtils;
12 | import org.apache.commons.io.IOUtils;
13 | import org.slf4j.Logger;
14 | import org.slf4j.LoggerFactory;
15 | import org.springframework.context.annotation.Configuration;
16 | import org.springframework.core.io.ClassPathResource;
17 | import org.springframework.util.ResourceUtils;
18 |
19 | import java.io.File;
20 | import java.io.FileNotFoundException;
21 | import java.io.IOException;
22 | import java.io.InputStream;
23 |
24 |
25 | @Configuration
26 | public class JniDispatchXGorgon extends AbstractJni {
27 | private static String soPath = "dylib/libcms.so";
28 | private static String soName = "libcms";
29 | private static String className = "com/ss/sys/ces/a";
30 | private static String methodSign = "leviathan(II[B)[B";
31 | private static Logger logger = LoggerFactory.getLogger(JniDispatchXGorgon.className);
32 | private static LibraryResolver createLibraryResolver() {
33 | return new AndroidResolver(23);
34 | }
35 |
36 | private static AndroidEmulator createARMEmulator() {
37 | return new AndroidARMEmulator("com.sun.jna");
38 | }
39 |
40 | private final AndroidEmulator emulator;
41 | private final Module module;
42 | private final VM vm;
43 |
44 | private final DvmClass Native;
45 |
46 | public JniDispatchXGorgon() {
47 | emulator = createARMEmulator();
48 | final Memory memory = emulator.getMemory();
49 | memory.setLibraryResolver(createLibraryResolver());
50 |
51 | vm = emulator.createDalvikVM(null);
52 | vm.setJni(this);
53 | vm.setVerbose(true);
54 | // File soFile = null;
55 | // try {
56 | // soFile = ResourceUtils.getFile("classpath:" + soPath);
57 | // } catch (FileNotFoundException e) {
58 | // e.printStackTrace();
59 | // }
60 | ClassPathResource resource = new ClassPathResource(soPath);
61 | File soFile = null;
62 | InputStream inputStream = null;
63 | try {
64 | inputStream = resource.getInputStream();
65 | File tempFile = File.createTempFile(soName, ".so");
66 | FileUtils.copyInputStreamToFile(inputStream,tempFile);
67 | soFile = tempFile;
68 | } catch (IOException e) {
69 | e.printStackTrace();
70 | }finally {
71 | IOUtils.closeQuietly(inputStream);
72 | }
73 | DalvikModule dm = vm.loadLibrary(soFile, false);
74 | dm.callJNI_OnLoad(emulator);
75 | this.module = dm.getModule();
76 |
77 | Native = vm.resolveClass(className);
78 |
79 | Symbol __system_property_get = module.findSymbolByName("__system_property_get", true);
80 | MemoryBlock block = memory.malloc(0x10);
81 | Number ret = __system_property_get.call(emulator, "ro.build.version.sdk", block.getPointer())[0];
82 | logger.info("sdk=" + new String(block.getPointer().getByteArray(0, ret.intValue())));
83 | try {
84 | Native.callStaticJniMethod(emulator, methodSign, -1,System.currentTimeMillis(),"".getBytes());
85 | }catch (Exception e){
86 |
87 | }
88 | logger.info("上述Native异常为必要初始化的操作,属于正常现象,请忽略");
89 |
90 | }
91 |
92 | private void destroy() throws IOException {
93 | emulator.close();
94 | }
95 |
96 | public byte[] callLeviathanMethod(int time,byte[] data){
97 |
98 | // Native.callStaticJniMethod(emulator, methodSign, -1,time,data);
99 |
100 | Object ret = Native.callStaticJniMethodObject(emulator, methodSign, -1,time,new ByteArray(vm,data));
101 |
102 | byte[] tt = (byte[]) ((DvmObject) ret).getValue();
103 | return tt;
104 | }
105 |
106 |
107 | public static void main(String[] args) throws Exception {
108 |
109 | JniDispatchXGorgon test = new JniDispatchXGorgon();
110 |
111 | test.destroy();
112 | }
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/src/main/java/com/douyin/spider/service/RegisterService.java:
--------------------------------------------------------------------------------
1 | package com.douyin.spider.service;
2 | import com.douyin.spider.jni.JniDispatchRegister;
3 | import com.douyin.spider.util.DouYinRegisterInfo;
4 | import com.douyin.spider.util.URLUtil;
5 | import okhttp3.*;
6 | import org.json.JSONObject;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.stereotype.Service;
11 | import java.io.ByteArrayOutputStream;
12 | import java.io.IOException;
13 | import java.util.Map;
14 | import java.util.zip.GZIPOutputStream;
15 |
16 |
17 | /**
18 | * @date :Created in 2021/06/18日12:05:47
19 | * @description:设备注册类
20 | * @modified By:wslmf
21 | * @version: $
22 | */
23 |
24 | @Service
25 | public class RegisterService {
26 | private static Logger logger = LoggerFactory.getLogger(RegisterService.class);
27 |
28 | public static void main(String[] args) {
29 | RegisterService deviceService = new RegisterService();
30 |
31 | Map registerMessage = deviceService.register();
32 | if (registerMessage != null) {
33 | logger.info("【register Message】" + registerMessage);
34 | }
35 | }
36 |
37 | @Autowired
38 | JniDispatchRegister jniRegister;
39 |
40 |
41 | public Map register() {
42 | // 获得设备信息
43 | Map deviceParams = DouYinRegisterInfo.getDeviceParams();
44 | // 构建注册请求体
45 | JSONObject registerInfo = DouYinRegisterInfo.getRegisterInfo(deviceParams);
46 | logger.debug("【registerInfo】"+registerInfo);
47 | // 先将请求体进行压缩
48 | byte[] data = compress(registerInfo.toString(), "utf-8");
49 | // 对data进行加密
50 | byte[] tt = jniRegister.callttEncryptMethod(data);
51 | // logger.info("string 类型"+ Arrays.toString(tt));
52 | // logger.info("byte 【"+ Arrays.toString((byte[]) ((DvmObject) ret).getValue()));
53 | String registerResponse = callRegisterUrl(deviceParams, tt);
54 | if (registerInfo == null) {
55 | return null;
56 | }
57 | Map registerResponseMap = new JSONObject(registerResponse).toMap();
58 | if (!registerResponseMap.containsKey("device_id")) {
59 | return null;
60 | }
61 |
62 | Map bodyParams = registerInfo.getJSONObject("header").toMap();
63 | // Map device_message = registerResponseJson.toMap();
64 | // 将注册成功的数据合并到deviceParams
65 | for (String key : registerResponseMap.keySet()) {
66 | if (key.equals("install_id_str")) {
67 | deviceParams.put("iid", registerResponseMap.get(key));
68 | }
69 | deviceParams.put(key, registerResponseMap.get(key));
70 | }
71 |
72 | // 将请求体的数据合并到deviceParams
73 | deviceParams.putAll(bodyParams);
74 | // 替换sim_serial_number ,由于bodyParams 中是 数组格式无法使用,在这里进行转化
75 | deviceParams.put("sim_serial_number", registerInfo.getJSONObject("header").getJSONArray("sim_serial_number").getJSONObject(0).getString("sim_serial_number"));
76 | logger.info("【device param 】" + new JSONObject(deviceParams));
77 | // 如果new_user=1必须进行激活
78 | appAlert(deviceParams);
79 | return deviceParams;
80 | }
81 |
82 |
83 | /**
84 | * @return java.lang.String
85 | * @Description //TODO 调用注册接口
86 | * @Date 2020/9/21 18:44
87 | * @Param [deviceParam, ttbody]
88 | **/
89 | public String callRegisterUrl(Map deviceParam, byte[] requestBody) {
90 |
91 | String url = "https://log.snssdk.com/service/2/device_register/?ac=wifi&mac_address=C0%3AEE%3AFB%3AD5%3A4B%3A16&channel=oppo&aid=2329&app_name=douyin_lite&version_code=110500&version_name=11.5.0&device_platform=android&ssmix=a&device_type=ONEPLUS+A3000&device_brand=OnePlus&language=zh&os_api=23&os_version=6.0.1&uuid=860046033047160&openudid=d4080df15130f0d9&manifest_version_code=110500&resolution=1080*1920&dpi=480&update_version_code=11509900&_rticket=1600423440596&mcc_mnc=46011&ts=1600423440&app_type=normal&cdid=4dda0a2b-6572-418c-bdfa-89cfd78a3aaf&tt_data=a&os_api=23&device_type=ONEPLUS%20A3000&ssmix=a&manifest_version_code=110500&dpi=480&uuid=860046033047160&app_name=douyin_lite&version_name=11.5.0&ts=1600423440&app_type=normal&ac=wifi&update_version_code=11509900&channel=oppo&_rticket=1600423440787&device_platform=android&version_code=110500&mac_address=C0%3AEE%3AFB%3AD5%3A4B%3A16&cdid=4dda0a2b-6572-418c-bdfa-89cfd78a3aaf&openudid=d4080df15130f0d9&device_id=40178045261&resolution=1080*1920&os_version=6.0.1&language=zh&device_brand=OnePlus&aid=2329&mcc_mnc=46011";
92 | url = URLUtil.replaceParam(url, deviceParam);
93 |
94 | logger.debug("【注册url】" + url);
95 | OkHttpClient client = new OkHttpClient().newBuilder()
96 | .build();
97 | MediaType mediaType = MediaType.parse("application/octet-stream;tt-data=a");
98 | RequestBody body = RequestBody.create(mediaType, requestBody);
99 | Request request = new Request.Builder()
100 | .url(url)
101 | .method("POST", body)
102 | .addHeader("Host", "log.snssdk.com")
103 | .addHeader("Connection", "keep-alive")
104 | .addHeader("sdk-version", "1")
105 | .addHeader("Content-Type", "application/octet-stream;tt-data=a")
106 | .addHeader("User-Agent", "com.ss.android.ugc.aweme/870 (Linux; U; Android 7.1.2; zh_CN; SM-G9650; Build/N2G47H; Cronet/58.0.2991.0)")
107 | .build();
108 | try {
109 | Response response = client.newCall(request).execute();
110 | String resp = response.body().string();
111 | logger.info("【注册返回结果】" + resp);
112 | return resp;
113 | } catch (IOException e) {
114 | e.printStackTrace();
115 | }
116 | return null;
117 | }
118 |
119 | /**
120 | * @return byte[]
121 | * @Description //TODO 注册前将请求体json进行压缩
122 | * @Date 2020/9/21 18:03
123 | * @Param [str, encoding]
124 | **/
125 | public byte[] compress(String str, String encoding) {
126 | if (str == null || str.length() == 0) {
127 | return null;
128 | }
129 | ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(8192);
130 | GZIPOutputStream gZIPOutputStream = null;
131 | try {
132 | gZIPOutputStream = new GZIPOutputStream(byteArrayOutputStream);
133 | gZIPOutputStream.write(str.getBytes(encoding));
134 | gZIPOutputStream.close();
135 | return byteArrayOutputStream.toByteArray();
136 | } catch (Throwable th) {
137 | try {
138 | gZIPOutputStream.close();
139 | } catch (IOException e) {
140 | e.printStackTrace();
141 | }
142 | }
143 | return null;
144 | }
145 |
146 | /**
147 | * @Description //TODO 设备激活
148 | * @Date 2020/9/22 12:09
149 | * @Param [device_params]
150 | * @return void
151 | **/
152 | public void appAlert(Map device_params){
153 | String url = "https://ichannel.snssdk.com/service/2/app_alert_check/?build_serial=37c96a14&timezone=8.0&carrier=CHN-CT&mcc_mnc=46011&sim_region=cn&sim_serial_number=89860320750105912020&device_id=40178045261&ac=wifi&mac_address=C0%3AEE%3AFB%3AD5%3A4B%3A16&channel=oppo&aid=2329&app_name=douyin_lite&version_code=110500&version_name=11.5.0&device_platform=android&ssmix=a&device_type=ONEPLUS+A3000&device_brand=OnePlus&language=zh&os_api=23&os_version=6.0.1&uuid=860046033047160&openudid=d4080df15130f0d9&manifest_version_code=110500&resolution=1080*1920&dpi=480&update_version_code=11509900&_rticket=1600423440642&ts=1600423440&app_type=normal&cdid=4dda0a2b-6572-418c-bdfa-89cfd78a3aaf&req_id=7522ead3-00cb-435c-9376-5dd2e012bc71&os_api=23&device_type=ONEPLUS%20A3000&ssmix=a&manifest_version_code=110500&dpi=480&uuid=860046033047160&app_name=douyin_lite&version_name=11.5.0&ts=1600423440&app_type=normal&ac=wifi&update_version_code=11509900&channel=oppo&_rticket=1600423440803&device_platform=android&version_code=110500&mac_address=C0%3AEE%3AFB%3AD5%3A4B%3A16&cdid=4dda0a2b-6572-418c-bdfa-89cfd78a3aaf&openudid=d4080df15130f0d9&device_id=40178045261&resolution=1080*1920&os_version=6.0.1&language=zh&device_brand=OnePlus&aid=2329&mcc_mnc=46011";
154 | url = URLUtil.replaceParam(url, device_params);
155 | logger.debug("【激活URL】"+url);
156 | OkHttpClient client = new OkHttpClient().newBuilder()
157 | .build();
158 | Request request = new Request.Builder()
159 | .url(url)
160 | .method("GET", null)
161 | .addHeader("Host", "ichannel.snssdk.com")
162 | .addHeader("Connection", "keep-alive")
163 | .addHeader("X-SS-REQ-TICKET", device_params.get("_rticket").toString())
164 | // .addHeader("X-Tt-Token", "0054151ee13867e63b34fceb2561855906969c4f162e9c5ceb4fa8923a01e8f767737d9e1aaa54e7877b190357b3247090a")
165 | .addHeader("sdk-version", "1")
166 | // .addHeader("x-tt-trace-id", "00-a0c903940995acc514d89fdbe82f0919-a0c903940995acc5-01")
167 | .addHeader("User-Agent", "com.ss.android.ugc.aweme.lite/110500 (Linux; U; Android 6.0.1; zh_CN; ONEPLUS A3000; Build/MMB29M; Cronet/TTNetVersion:4df3ca9d 2019-11-25)")
168 | .build();
169 | try {
170 | Response response = client.newCall(request).execute();
171 | logger.debug("【激活情况】"+response.body().string());
172 | } catch (IOException e) {
173 | e.printStackTrace();
174 | }
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/src/main/java/com/douyin/spider/service/XGorgonService.java:
--------------------------------------------------------------------------------
1 | package com.douyin.spider.service;
2 |
3 |
4 | import com.douyin.spider.jni.JniDispatchXGorgon;
5 | import com.douyin.spider.util.URLUtil;
6 | import okhttp3.OkHttpClient;
7 | import okhttp3.Request;
8 | import okhttp3.Response;
9 | import org.apache.commons.codec.digest.DigestUtils;
10 | import org.json.JSONObject;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.stereotype.Service;
15 |
16 | import java.io.IOException;
17 | import java.util.HashMap;
18 | import java.util.Map;
19 |
20 | /**
21 | * @date :Created in 2020/9/22 10:08
22 | * @description:X-gorgon签名获取
23 | * @modified By:wslmf
24 | * @version: $
25 | */
26 | @Service
27 | public class XGorgonService {
28 | private static Logger logger = LoggerFactory.getLogger(XGorgonService.class);
29 |
30 | @Autowired
31 | JniDispatchXGorgon jniXGorgon;
32 |
33 | /**
34 | * @Description //TODO 获得URL 参数列表的指定参数param
35 | * @Date 2020/9/22 10:24
36 | * @Param [url, param]
37 | * @return java.lang.String
38 | **/
39 | public static String getParam(String url,String param){
40 | int begin = url.indexOf("?")>0? url.indexOf("?")+1:0;
41 | String uri = url.substring(begin);
42 | String[] params = uri.split("&");
43 | for(String value:params){
44 | if(value.contains(param) && value.indexOf(param)==0){
45 | return value.substring(value.indexOf("=")+1);
46 | }
47 | }
48 | return "";
49 | }
50 |
51 | /**
52 | * @Description //TODO 根据URL生成X-gorgon
53 | * @Date 2020/9/22 10:36
54 | * @Param [url]
55 | * @return java.util.Map
56 | **/
57 | public Map generateXGorgon(String url){
58 | // 根据uri加密后生成字符串
59 | String uri = url.substring(url.indexOf("?")+1);
60 | logger.debug("【uri】"+uri);
61 | String bodyData = getBodyData(uri);
62 | logger.debug("【body Data】"+bodyData);
63 | // 在调用so之前进行编码转化
64 | byte[] data = beforeEncode(bodyData);
65 | String ts = getParam(url, "ts");
66 | if(ts.isEmpty()){
67 | ts = String.valueOf(System.currentTimeMillis()/1000);
68 | }
69 | int time = Integer.valueOf(ts);
70 | logger.debug("【time】"+time);
71 | // 调用本地so文件
72 | byte[] tt = jniXGorgon.callLeviathanMethod(time, data);
73 | //在调用so之后进行解码转化
74 | String x_gorgon = afterDecode(tt);
75 | HashMap resp = new HashMap<>();
76 | resp.put("X-Gorgon",x_gorgon);
77 | resp.put("X-Khronos",time);
78 | resp.put("url",url);
79 | logger.info("【resp】"+resp);
80 | return resp;
81 | }
82 |
83 | public static void getVideoList(String url,String x_gorgon,String x_khronos){
84 | OkHttpClient client = new OkHttpClient().newBuilder()
85 | .build();
86 | Request request = new Request.Builder()
87 | .url(url)
88 | .method("GET", null)
89 | .addHeader("Host", "aweme-hl.snssdk.com")
90 | .addHeader("Connection", "keep-alive")
91 | .addHeader("X-SS-REQ-TICKET", getParam(url,"_rticket"))
92 | .addHeader("sdk-version", "1")
93 | .addHeader("User-Agent", "com.ss.android.ugc.aweme.lite/110500 (Linux; U; Android 6.0.1; zh_CN; ONEPLUS A3000; Build/MMB29M; Cronet/TTNetVersion:4df3ca9d 2019-11-25)")
94 | .addHeader("X-Gorgon", x_gorgon)
95 | .addHeader("X-Khronos", x_khronos)
96 | .build();
97 | try {
98 | Response response = client.newCall(request).execute();
99 | logger.debug(response.body().string());
100 | } catch (IOException e) {
101 | e.printStackTrace();
102 | }
103 | }
104 |
105 |
106 | /**
107 | * @Description //TODO 根据uri加密后生成字符串
108 | * @Date 2020/9/22 10:36
109 | * @Param [uri]
110 | * @return java.lang.String
111 | **/
112 | public String getBodyData(String uri){
113 | JSONObject str = new JSONObject();
114 | // String uri = "source=0&max_cursor=0&sec_user_id=MS4wLjABAAAAxA44mxJVod_Aq5wc0cZrbZHJ2S_DnoJctGpb_mOvsxs&count=20&os_api=25&device_type=SM-G9650&ssmix=a&manifest_version_code=870&dpi=320&uuid=860046033047160&app_name=douyin_lite&version_name=8.7.0&ts=1600421993&app_type=normal&ac=wifi&update_version_code=8702&channel=aweGW&_rticket=1600421993106&device_platform=android&iid=738485302461095&version_code=870&mac_address=52:54:00:24:57:5f&cdid=c72cc213-26f1-40e2-aa7b-1aa41c01a502&openudid=ad9e4ed558079d9e&device_id=52205205146&resolution=1440*2960&os_version=7.1.2&language=zh&device_brand=samsung&aid=1128&mcc_mnc=46011";
115 | str.put("param",uri);
116 | str.put("stub","");
117 | str.put("cookie","");
118 | str.put("sessionid","");
119 | String param = str.getString("param");
120 | String stub = str.getString("stub");
121 | String cookie = str.getString("cookie");
122 | String sessionid = str.getString("sessionid");
123 |
124 | String str2 = "00000000000000000000000000000000";
125 | String md5 = (param == null ||param.length()<=0?str2 : DigestUtils.md5Hex(param.getBytes()));
126 | if(stub == null ||stub.length()<=0){
127 | stub = str2;
128 | }
129 | String md52 = (cookie == null ||cookie.length()<=0 ? str2 :DigestUtils.md5Hex(cookie.getBytes()));
130 |
131 | if(sessionid != null && sessionid.length() > 0){
132 | str2 = DigestUtils.md5Hex(sessionid.getBytes());
133 | }
134 | return md5+stub+md52+str2;
135 | }
136 |
137 | /**
138 | * @Description //TODO 在调用so之前进行编码转化
139 | * @Date 2020/9/22 10:37
140 | * @Param [str]
141 | * @return byte[]
142 | **/
143 | public byte[] beforeEncode(String str) {
144 | int length = str.length();
145 | byte[] bArr = new byte[(length / 2)];
146 | for (int i = 0; i < length; i += 2) {
147 | bArr[i / 2] = (byte) ((Character.digit(str.charAt(i), 16) << 4) + Character.digit(str.charAt(i + 1), 16));
148 | }
149 | return bArr;
150 | }
151 |
152 | /**
153 | * @Description //TODO 在调用so之后对Byte进行解码转化
154 | * @Date 2020/9/22 10:37
155 | * @Param [bArr]
156 | * @return java.lang.String
157 | **/
158 | public String afterDecode(byte[] bArr) {
159 | if (bArr == null) {
160 | return null;
161 | }
162 | char[] charArray = "0123456789abcdef".toCharArray();
163 | char[] cArr = new char[(bArr.length * 2)];
164 | for (int i = 0; i < bArr.length; i++) {
165 | int b2 = bArr[i] & 255;
166 | int i2 = i * 2;
167 | cArr[i2] = charArray[b2 >>> 4];
168 | cArr[i2 + 1] = charArray[b2 & 15];
169 | }
170 | return new String(cArr);
171 | }
172 |
173 | public static void main(String[] args) throws IOException {
174 | RegisterService deviceService = new RegisterService();
175 | Map registerMessage = deviceService.register();
176 | if (registerMessage != null) {
177 | logger.info("【register Message】" + registerMessage);
178 | }
179 | String url ="https://aweme.snssdk.com/aweme/v1/aweme/post/?source=0&max_cursor=0&sec_user_id=MS4wLjABAAAAryNwJa_HtclngdC-xXIKvG8liaveo5h4kiOjIBt5I1ml76MM-WRniwqzWDIZREl9&count=20&os_api=23&device_type=ONEPLUS%20A3000&ssmix=a&manifest_version_code=110500&dpi=480&uuid=863581039914077&app_name=douyin_lite&version_name=11.5.0&ts=1600745725&app_type=normal&ac=wifi&update_version_code=11509900&channel=oppo&_rticket=1600745727371&device_platform=android&iid=3518051136579950&version_code=110500&mac_address=C0%3AEE%3AFB%3AE0%3A31%3A89&cdid=dfd60f13-53ca-42eb-8af9-d187f5ca2edc&openudid=a9fc3bd6e5c99814&device_id=39796983352&resolution=1080*1920&os_version=6.0.1&language=zh&device_brand=OnePlus&aid=2329";
180 | url = URLUtil.replaceParam(url, registerMessage);
181 | XGorgonService xgorgonService = new XGorgonService();
182 | Map stringObjectMap = xgorgonService.generateXGorgon(url);
183 | logger.info(stringObjectMap.toString());
184 | getVideoList(url,stringObjectMap.get("X-Gorgon").toString(),stringObjectMap.get("X-Khronos").toString());
185 | }
186 |
187 | }
188 |
--------------------------------------------------------------------------------
/src/main/java/com/douyin/spider/util/DouYinRegisterInfo.java:
--------------------------------------------------------------------------------
1 | package com.douyin.spider.util;
2 |
3 | import org.json.JSONObject;
4 |
5 | import java.util.*;
6 |
7 | /**
8 | * 整理抖音设备注册信息
9 | */
10 | public class DouYinRegisterInfo {
11 |
12 | /**
13 | * @return java.util.Map
14 | * @Description //TODO 设备信息初始化
15 | * @Param []
16 | **/
17 | public static Map getDeviceParams() {
18 | String uuid = "3529" + String.valueOf(new Random().nextInt(999)) + (new Random().nextInt(899999999) + 100000000);
19 | long time = System.currentTimeMillis();
20 | Map deviceParams = new HashMap<>(32);
21 | deviceParams.put("ac", "wifi");
22 | deviceParams.put("aid", "2329");
23 | deviceParams.put("channel", "ky_douyinlite_and31"); //oppo
24 | deviceParams.put("device_brand", "Xiaomi");//OnePlus
25 | deviceParams.put("device_type", "MI%209"); //ONEPLUS%20A3000
26 | deviceParams.put("dpi", "320");
27 | deviceParams.put("language", "zh");
28 | deviceParams.put("manifest_version_code", "120500"); //110500
29 | deviceParams.put("os_api", "23");
30 | deviceParams.put("os_version", "6.0.1");
31 | deviceParams.put("update_version_code", "12509900"); //11509900
32 | deviceParams.put("version_code", "120500"); //110500
33 | deviceParams.put("version_name", "12.5.0"); //11.5.0
34 | deviceParams.put("uuid", uuid);
35 | deviceParams.put("openudid", UUID.randomUUID().toString().replaceAll("-", "").substring(16));
36 | deviceParams.put("mac_address", randomMac());
37 | deviceParams.put("cdid", UUID.randomUUID().toString());
38 | deviceParams.put("sim_serial_number", ""); // 89860042191573218602
39 | deviceParams.put("rom", "OnePlus");
40 | deviceParams.put("rom_version", "9");
41 | deviceParams.put("sdk_version", "9");
42 | deviceParams.put("cpu_abi", "arm64-v8a");
43 | deviceParams.put("device_model", "MI%209"); // ONEPLUS%20A3000
44 | deviceParams.put("resolution", "1080*1920");
45 | deviceParams.put("_rticket", time);
46 | deviceParams.put("ts", time / 1000);
47 | return deviceParams;
48 | }
49 |
50 |
51 | /**
52 | * @return org.json.JSONObject
53 | * @Description //TODO 设备信息注册请求体
54 | * @Param [deviceParams]
55 | **/
56 | public static JSONObject getRegisterInfo(Map deviceParams) {
57 |
58 | Map temp = new HashMap<>(16);
59 | if (deviceParams.containsKey("sim_serial_number")) {
60 | String sim_serial_number = deviceParams.get("sim_serial_number").toString();
61 | temp.put("sim_serial_number", sim_serial_number);
62 | } else {
63 | temp.put("sim_serial_number", ""); //89860118841817353175
64 | }
65 | List