Use the go language to write a Windows plug-in (top)

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

I work in an Internet finance company, for an internet financial company, the most basic function is the client deposit and withdrawal, and the stability of the gold is very important, out of the gold is easy to lead to investor panic, this article is about the gold, out of the gold interface we docking is the Bank of China Merchants Banking Direct system, So what kind of program is the silver-Enterprise Direct-connect system?

Yes, this program is running on windows and needs to be plugged into usbkey to work properly, which means that you can't simply use the command line for operations management.

See here, do operations of the classmate's heart and I should be the same as the collapse of.

Explain to you, this service is to do what, we can take this program as our business system and Merchants Bank communication Messenger, all the withdrawal operation, query operation through this messenger to complete.

Due to various unknown reasons, such as network instability, or usbkey insertion time too long produced some inexplicable error, then need to manually restart the service or re-login account, and, this work is sometimes at night operation, which is equivalent to 24 hours standby ah, although the fault frequency is not high, But this string is always broken, it is simply destroying my happy life.

I can't do this kind of physical work, so I must give it to someone else to do it.

Do not think more, "others" can only be a plug-in only, who do not like to do this kind of human physical life.

So with my 18-year-old development experience, I think of the Windows message model, using SendMessage the corresponding form control handle to send a specific event is not done, the exception is automatically restarted use CreateProcess it?

Innocent words that are filled with my mind SendMessage

LRESULT WINAPI SendMessage(  _In_ HWND   hWnd,  _In_ UINT   Msg,  _In_ WPARAM wParam,  _In_ LPARAM lParam);

Have the wood has very familiar appearance, surprised not pleasantly, open not happy? Is it OK to send keyboard click events, mouse click events?

Later on, it will take a lot of work to complete a relatively perfect available plug-in software, SendMessage basically can only solve a part of the problem

However, when I finished this code, I still feel too much trouble, because the key wizard this kind of software can be solved, why do you have to do it myself? But finally gave up this idea, because this is a very important service, perhaps in the future will have a good 几千个亿 financial fate, if the installation of unknown software, how to protect the security of funds??? It is absolutely impossible to make such a hasty decision, so it is decided to be honest with the code ...

What language is a problem, can be used on Windows C++ , C# series, and C# I remember there is a automation framework can do similar operations, but I have been using the last 3 years, the golang first two languages are now only occasionally used rhythm, So basically in the state of Rusty, but golang also support the use syscall windows of the call DLL (dynamic link library), so decisive use golang , because this plug-in most of the WINAPI are in user32.dll and kernel32.dll , we only need to be able to load these several can call the powerful WinAPI .

You can use PE Explorer to see what output functions a DLL has

var (    moduser32 = syscall.NewLazyDLL("user32.dll")    procSendMessage = moduser32.NewProc("SendMessageW")    procPostMessage = moduser32.NewProc("PostMessageW"))func SendMessage(hwnd HWND, msg uint32, wParam, lParam uintptr) uintptr {    ret, _, _ := procSendMessage.Call(        uintptr(hwnd),        uintptr(msg),        wParam,        lParam)    return ret}...

As you can see, here we are using SendMessageW , instead SendMessageA , because the go language underlying calls the DLL interface, the incoming is utf16 , look at the following code to understand

func SetWindowText(hwnd HWND, text string) {    procSetWindowText.Call(        uintptr(hwnd),        uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(text))))}

This is an API to set the title of the form, the first parameter is the form handle, the second argument you can see, is to convert the go language string to UTF16 format, and get its pointer.

It is also worth noting that if we compile the program is 32位 , then try not to use as a 64位 program plug-in, because there are a lot of complex features can not be implemented, the subsequent mention of this section, 银企直连 the service is 32-bit, so our go language is also installed 32-bit, At the same time, for better compiling tests, my virtual machine is loaded with an Win2008 R2 32位 operating system

So how do we send a message to a form? Can you do the experiment first and not write the code? The answer is yes, we first call out our artifact,Spy++

Dragging a crosshair to a specific window will give you a handle to the window, and we can do the same with FINDWINDOWW or enumchildwindows.

Two steps required for a direct banking company to work properly

    1. Start HTTP Service Listener
    2. Login

Let's take a look at the Start HTTP listener button

We used the spy++ handle that caught the toolbar.

Then use the spy++ first button to send a mouse click event, then you can turn on the monitoring

Click action in Windows message, is divided into two actions, one is WM_LBUTTONDOWN and the other is WM_LBUTTONUP , so we need to send two events, when the completion of these two send, we can see the following interface

Yes, actually here is a pit, start monitoring is not good to start, must pop up a message box, accompanied by the spy++ card is dead, why? Because we are using SendMessage , this is a synchronous process, because a message box appears, so the spy++ return message has not been received, so it is stuck. When we click on the confirmation button we can restore it, of course, we can use it PostMessage , but this interface is only suitable for those who do not care about execution results.

Well, here we have the first pit: There are pop-up windows, we need to automatically identify the plug-in, and can automatically close the pop-up window.

OK, let's go, we should start landing.

The wparam we have just now SendMessage is 1, so this button is 4.

Image.png

Continue using the spy++ send message

After the simulation sent, the whole person suddenly is not good, because this button does not respond, the following two parameters you do not know what is good, in the whole trapped in the time, found that we can actually through the shortcut key to ctrl+b complete the monitoring, ctrl+i enter the login interface

Usbkey is not inserted at this time

So, we need to use another API: SendInput including the following password input, as well as using this API

Let's take a look at the definition of this API

UINT WINAPI SendInput(  _In_ UINT    nInputs, // 按键数量  _In_ LPINPUT pInputs, // 按键内容数组  _In_ int     cbSize // 数组内容结构体的尺寸);

Looks very stuffed, a bunch of parameters.

As this article is about research, we assume that the key simulation SendInput can be done shortcut keys, password input key simulation, in fact, this API is actually working, because this interface is the real analog keyboard input, not for a window handle.

Next we will usher in the second pit, if Usbkey normal work, then the user name content is automatically filled in,

This user name is read from the Usbkey, read it takes time, so we can continue to send a message to this text box here, WM_GETTEXT get the user name, if the user name is expected data, we think at this time Usbkey is normal work, otherwise if the long-time user name did not load successfully, It indicates that usbkey work is abnormal and should send alarm information.

We'll probably get the following kinds of errors

    • Password error
    • Communication failure
    • Usbkey has a problem.

For password error This problem, our plug-in should stop work immediately, because password input more than limit, Usbkey will lock, the company out of the gold service hung up ....

Why is the password entered incorrectly? Because there is a good chance that the other program will interfere with the automatic input.
We'll try SetForegroundWindow to keep the window in front of the code as an active state.

So for communication failure, the solution is to try again

The rest of the problem, I personally think the issue of alarm, manual treatment will be more appropriate.

With two new questions at this point,

    1. How do we know what the contents of the message box are?
    2. How do we know if the plug-in is successful?

For the first question, we can walk through the EnumChildWindows child handle of the message box and then we GetWindowText can know what it is.

We're going to focus on the second one.

Here are two solutions:

    1. To initiate a query request to the Bank of merchants, if you can query the data, indicating the successful login
    2. Check the contents of the login information

Login Information List

In order to improve the difficulty, we choose Scenario 2

This method is more difficult, there are difficulties, we have to solve, no difficulties we also have to create difficulties to solve ....

Why is it difficult?

Because we have no way SendMessage WM_GETTEXT to get content by sending events, but we can LVM_GETITEMTEXT get the list contents of the ListView by

But ..... Cross-process so take is not get, at the same time, the process of different numbers, also cannot get the data.

How to solve?

We need to use the API VirtualAllocEx to apply for a piece of memory space to the silver-to-enterprise direct process, for our plug-in process and silver-direct-link data communication, when we send a LVM_GETITEMTEXT message, we need to write the parameter information into this memory block, and then use SendMessage , The data in the ListView will be written to this memory block, and finally we can ReadProcessMemory read the data obtained from the list by

This is why 32位 you cannot read the 64位 contents of the program, although we can use WriteProcessMemory and ReadProcessMemory to write and read the data in the process memory, but because of the interaction through this mechanism, the size of the pointer is different, through the SendMessage command although it can be executed successfully, But the content of the write-back will run.

Arrows represent data flow, and all API calls are done on the side of the plug.

The whole process is probably the case, we need to use the memory block of the remote process to do the data interaction, but finally remember to make sure VirtualFreeEx that the unused block of memory is used.

There should be a summary here:

    1. Use the analog keyboard method to turn on the monitor and enter into the login interface instead ofSendMessage
    2. Get the contents of a login result by remotely requesting a memory block
    3. The contents of the popup message box need to be judged to determine if there is an exception and to close the message window

So far, the key technical content has been investigated, the next one we'll talk about how to use the go language to implement a really usable plug-in.
Let's start by previewing a few plug-ins:

Plug-in work .....

When a stability anomaly occurs, an alarm is sent through the Bearychat incoming service

Welcome to my public number:deepin-z

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.