preface
Poke here → Kangkang, how many websites have you registered your mobile phone number!!!
Friendly recommendation: New generation secure SMS
This paper introduces in detail all the processes of cracking the pole test sliding verification code, including the cracking idea, implementation steps and test results. I believe you can easily crack the sliding verification code after reading it; #SMS flood control bombing#
I. composition of analytical verification code
From the above three pictures, the polar sliding puzzle verification code is composed of a small puzzle and a large background picture. The shapes of the puzzle are various, and there is a shadow gap in the background picture, which is consistent with the shape of the puzzle.
Here we use the F12 method to open the browser console and observe the page structure of the verification code.
Through observation, we can see that the pictures contained in the verification code are presented on the page in the form of < canves > canvas, and there are three pictures, and the third picture is added with the attribute style = "display: none;", That is, it is hidden and not displayed. So let's modify the page code to see what this picture is.
After modifying the code, I found that this is the complete background picture. According to the above naming, we can basically determine what these three figures are.
-
The first class is geetest_canvas_bg geetest_absolute, which can be determined as the background image with notch.
-
The second class is geetest_canvas_slice geetest_absolute, which can be determined as a puzzle.
-
The third is the complete picture.
II. Analyze the crack ideas
- First, analyze what we should do according to the composition of the verification code:
According to the normal manual operation process, we need to see the position of the shadow gap corresponding to the puzzle in the background image, and then press and hold the lower slider to align the puzzle to the gap position to complete the verification.
- Then analyze what the program needs to do according to what people want to do:
According to the analysis, the following steps are obtained:
1. Obtain two pictures (with gap background and complete background)
2. Process the picture, get the shadow position and calculate the sliding distance
3. Simulate sliding according to sliding distance
III. specific operation steps
1. Get two pictures
Since the pictures here are rendered through canvas canvas, we can generate pictures by executing js code.
Can refer to How to capture pictures in canvas.
2. Process pictures and calculate the sliding distance
From the two pictures obtained in the first step, we can see that there are two different places in the two pictures, one is small and the other is large. We can determine the position of the shadow gap by comparing the difference of each pixel. The distance between the abscissa of the notch position minus the distance between the small drawing and the frame is the sliding distance.
The following is the key part of the code:
private final String INDEX_URL = "https://www.geetest.com/Register"; // Lazy loading private static WebElement waitWebElement(WebDriver driver, By by, int count) throws Exception { WebElement webElement = null; boolean isWait = false; for (int k = 0; k < count; k++) { try { webElement = driver.findElement(by); if (isWait) System.out.println(" ok!"); return webElement; } catch (org.openqa.selenium.NoSuchElementException ex) { isWait = true; if (k == 0) System.out.print("waitWebElement(" + by.toString() + ")"); else System.out.print("."); Thread.sleep(50); } } if (isWait) System.out.println(" outTime!"); return null; } /** * Calculate the distance to be translated * * @param driver * @param fullImgPath Full background picture file name * @param bgImgPath File name with gap background picture * @return * @throws IOException */ public static int getMoveDistance(WebDriver driver, String fullImgPath, String bgImgPath) throws IOException { File fullFile = new File(fullImgPath); File bgFile = new File(bgImgPath); try { BufferedImage fullBI = ImageIO.read(fullFile); BufferedImage bgBI = ImageIO.read(bgFile); for (int i = 0; i < bgBI.getWidth(); i++) { for (int j = 0; j < bgBI.getHeight(); j++) { int[] fullRgb = new int[3]; fullRgb[0] = (fullBI.getRGB(i, j) & 0xff0000) >> 16; fullRgb[1] = (fullBI.getRGB(i, j) & 0xff00) >> 8; fullRgb[2] = (fullBI.getRGB(i, j) & 0xff); int[] bgRgb = new int[3]; bgRgb[0] = (bgBI.getRGB(i, j) & 0xff0000) >> 16; bgRgb[1] = (bgBI.getRGB(i, j) & 0xff00) >> 8; bgRgb[2] = (bgBI.getRGB(i, j) & 0xff); if (difference(fullRgb, bgRgb) > 255) { return i; } } } } catch (Exception e) { return 0; } finally { fullFile.delete(); bgFile.delete(); } return 0; } private static int difference(int[] a, int[] b) { return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]) + Math.abs(a[2] - b[2]); } /** * // Execute JS code and generate pictures * * @param driver * @param jsString * @param input * @return Picture path */ public static String getImgByJs(WebDriver driver, String jsString) { try { String imgFilePath = "c://GeeTest_" + System.currentTimeMillis() + "_" + (Math.random() * 9 + 1) * 100000 + ".jpg"; String imgInfo = ((JavascriptExecutor) driver).executeScript(jsString).toString(); if (imgInfo != null && imgInfo.contains("data")) { imgInfo = imgInfo.substring(imgInfo.indexOf(",") + 1); ByteArrayOutputStream outputStream = imgStrToFile(imgInfo); if (outputStream != null) { byte[] picBytes = outputStream.toByteArray(); outPicToFile(picBytes, imgFilePath); return imgFilePath; } } return null; } catch (Exception e) { return null; } } /** * Convert base64 byte code to byte output stream * * @param imgBase64Str * @return */ private static ByteArrayOutputStream imgStrToFile(String imgBase64Str) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try { if (imgBase64Str != null) { BASE64Decoder decoder = new BASE64Decoder(); byte[] data = decoder.decodeBuffer(imgBase64Str); outputStream.write(data); outputStream.flush(); } return outputStream; } catch (Exception e) { return null; } } /** * Picture circulation picture * * @param o * @param imgFilePath */ private static void outPicToFile(Object o, String imgFilePath) { if (o == null) return; try { if (o instanceof byte[]) { // Convert to picture if (((byte[]) o).length == 0) return; File imgFile = new File(imgFilePath); // byte array to picture FileImageOutputStream imageOutput = new FileImageOutputStream(imgFile); imageOutput.write((byte[]) o, 0, ((byte[]) o).length); imageOutput.close(); } else { return; } } catch (Exception e) { } } /** * Simulated manual movement * * @param driver * @param element Page slider * @param distance Need to move distance * @throws InterruptedException */ public static void move(WebDriver driver, WebElement element, int distance) throws InterruptedException { int randomTime = 0; if (distance > 90) { randomTime = 250; } else if (distance > 80 && distance <= 90) { randomTime = 150; } List<Integer> track = getMoveTrack(distance - 2); int moveY = 1; try { Actions actions = new Actions(driver); actions.clickAndHold(element).perform(); Thread.sleep(200); for (int i = 0; i < track.size(); i++) { actions.moveByOffset(track.get(i), moveY).perform(); Thread.sleep(new Random().nextInt(300) + randomTime); } Thread.sleep(200); actions.release(element).perform(); } catch (Exception e) { e.printStackTrace(); } } /** * Obtain the sliding track according to the distance * * @param distance Distance to move * @return */ public static List<Integer> getMoveTrack(int distance) { List<Integer> track = new ArrayList<>();// Moving track Random random = new Random(); int current = 0;// Distance moved int mid = (int) distance * 4 / 5;// Deceleration threshold int a = 0; int move = 0;// Distance per cycle while (true) { a = random.nextInt(10); if (current <= mid) { move += a;// Accelerating } else { move -= a; } if ((current + move) < distance) { track.add(move); } else { track.add(distance - current); break; } current += move; } return track; } private void seleniumTest() { ChromeDriverManager manager = ChromeDriverManager.getInstance(); int status = -1; String phone = "13814389438"; try { WebDriver driver = manager.getDriver(); driver.get(INDEX_URL); driver.manage().window().maximize(); // Set browser window maximization Thread.sleep(2000); // Enter mobile number WebElement phoneElemet = waitWebElement(driver, By.xpath("//input[@placeholder = 'mobile number'] "), 20); phoneElemet.clear(); for (int i = 0; i < phone.length(); i++) { char c = phone.charAt(i); phoneElemet.sendKeys(c + ""); phoneElemet.click(); } sleep(50); // Click to get the verification code waitWebElement(driver, By.className("sendCode"), 20).click(); sleep(2000); // Complete background image geetest_canvas_fullbg geetest_fade geetest_absolute String fullImgJs = "return document.getElementsByClassName(\"geetest_canvas_fullbg geetest_fade geetest_absolute\")[0].toDataURL(\"image/png\");"; String fullImgPath = getImgByJs(driver, fullImgJs); // Background image with gap geetest_canvas_bg geetest_absolute String bgImgJs = "return document.getElementsByClassName(\"geetest_canvas_bg geetest_absolute\")[0].toDataURL(\"image/png\");"; String bgImgPath = getImgByJs(driver, bgImgJs); // Get slide button WebElement moveElemet = waitWebElement(driver, By.className("geetest_slider_button"), 20); // Get the sliding distance and delete the picture int distance = getMoveDistance(driver, fullImgPath, bgImgPath); if (distance == 0) { } // slide move(driver, moveElemet, distance - 6); // Sliding result sleep(2 * 1000); String gtInfo = waitWebElement(driver, By.className("sendCode"), 20).getAttribute("innerHTML"); System.out.println(gtInfo); } catch (Exception e) { e.printStackTrace(); } finally { manager.closeDriver(status); } } protected static void sleep(long time) { try { Thread.sleep(time); } catch (InterruptedException e) { } }
3. Simulate sliding according to sliding distance
After getting the sliding distance, let's look at the sliding track. If the sliding track is too regular, it is easy to be recognized. Therefore, we can close the sliding track to the normal operation track of human beings.
For example: first fast and then slow, and slowly align with the gap. Shake left and right at the notch. Stay at the gap, appreciate the results, etc.
IV. result display
V. result analysis
Objectives:
Identify the shadow position, calculate the corresponding sliding distance and simulate sliding.
Realization idea:
1. Obtain two pictures (complete picture and gap picture)
2. Process the picture, get the shadow position and calculate the sliding distance
3. Simulate sliding according to sliding distance
Identification time:
15 - 50 ms
Pass rate:
>95%
Vi. conclusion
This article ends here. Thank you for stopping to watch. Pay attention and praise~
Thank you, boss~
Poke here → Kangkang, how many websites have you registered your mobile phone number!!!
Google has announced its withdrawal from the graphic verification code service. Why are all kinds of wonderful verification methods emerging in China? How is the security?
Tencent waterproof wall sliding puzzle verification code
Baidu rotating picture verification code
Netease shield Slide Puzzle verification code
Verification code for point selection of top image area
Top image sliding puzzle verification code
Polar sliding puzzle verification code
Using deep learning to crack captcha verification code