# sougou search app weixin official account list so encryption algorithm analysis reduction RSA encryption Base64 analysis

Keywords: Algorithm

# const Longge = Function() {}

const a = omnipotent silly treasure, who shares various operations in a different posture every day. He has been sharing cryptography in recent October;
const b = Click join planet;
return "invincible dragon brother";

# preface

If you want to learn the restoration of unidbg android reverse cryptography algorithm, you can call Longge ();
Then the last article analyzes the encryption logic of rsa base64

# 0x1

The last article analyzed the static registration logic of so

That's right here. Click in

There are five parameters in total. The first two are default, namely jnienv, jobject or jclass. The last three are passed in
The above is done with some string initialization and called j_. Sc_ Encryptwallencode function, click to see

After entering, there are three functions that need our attention. The first two are not very important after analysis. We mainly analyze the last one

Thanks for not removing the code symbols, you can see the dense algorithms inside

In the next analysis, we can see that we are familiar with the string. Isn't it the request parameter of the previous request package? Here is the encryption logic of all algorithms

# 0x2

There are many algorithms inside. Let's analyze rsa and base64 this time

### rsa

The previous are some conventional judgment assignment operations

v10 = operator new(48u);
This line is to create a memory with a size of 48 bytes, and v10 only has the memory address

EncryptWall::WallKey::WallKey(v10);
Here, call a function to enter the memory address and click to see it

#### EncryptWall::WallKey::WallKey

The click in logic is also relatively simple. The two do while loops a total of 48 times, just filling in the space of 48 bytes of memory

lrand48() function under linux
Randomly generate long integers between 0 - 2 ^ 31

Tips: continue down

v12 = RSA_Encrypt(v10 + 16, 32u, &v60, &v59);
Here is to call the rsa encryption function. The four parameters are the first address of v10 plus 16 and 32 numbers, the address of v60 and the address of v59

#### RSA_Encrypt

n_crypto::SetSignPubKey
Here is to generate public_key, module and index are passed in

n_crypto::PublicEnc(v8, v9, v6, &v11, v4);
Call this function to start encryption. There are five parameters in total
They are 1:32 byte address, 2:32 number, 3:128 byte memory, 4: memory address and 5:80 byte memory address

Tips: end of RSA analysis

### base64Encode

Here is the encryption result of rsa. Here is another layer of base64 coding. You can verify whether it is standard base64 later

# 0x3

The algorithm analysis is almost complete. Use the console debugger and hook functions of unidbg to verify the data. Those unfamiliar with it can see the above recommended articles

### unidbg unicorn inline hook

First, use the EncryptWall::WallKey::WallKey function to see what data is generated

```public void hookUnicornWallKey() {
@Override
public void onAttach(Unicorn.UnHook unHook) {
}

@Override
public void detach() {
}

@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xB332)) {
System.out.println("Hook By Unicorn hookUnicornWallKey");
RegisterContext ctx = emulator.getContext();
Pointer input1 = ctx.getPointerArg(0);
Inspector.inspect(input1.getByteArray(0, 0x100), " Parameter 1");
}
if (address == (module.base + 0xB336)) {
RegisterContext ctx = emulator.getContext();
Inspector.inspect(ctx.getPointerArg(0).getByteArray(0, 0x100), " Unicorn hook hookUnicornWallKey");
}
}
}, module.base + 0xB332, module.base + 0xB336, null);
}
```

As you can see from the running result, it is just 48 bytes of data

Then hook rsa base64 function respectively

```public void hookUnicornRsa() {
@Override
public void onAttach(Unicorn.UnHook unHook) {
}

@Override
public void detach() {
}

@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xB34E)) {
RegisterContext ctx = emulator.getContext();
Pointer input1 = ctx.getPointerArg(0);
Inspector.inspect(input1.getByteArray(0, 0x100), " hookUnicornRsa Parameter 1");
}
if (address == (module.base + 0xB352)) {
RegisterContext ctx = emulator.getContext();
Inspector.inspect(ctx.getPointerArg(0).getByteArray(0, 0x100), " Unicorn hook hookUnicornRsa");
}
}
}, module.base + 0xB34E, module.base + 0xB352, null);
}

public void hookUnicornBase64Encode() {
@Override
public void onAttach(Unicorn.UnHook unHook) {
}

@Override
public void detach() {
}

@Override
public void hook(Backend backend, long address, int size, Object user) {
if (address == (module.base + 0xB372)) {
RegisterContext ctx = emulator.getContext();
Pointer input1 = ctx.getPointerArg(0);
Inspector.inspect(input1.getByteArray(0, 0x100), " hookUnicornBase64Encode Parameter 1");
}
if (address == (module.base + 0xB376)) {
RegisterContext ctx = emulator.getContext();
Inspector.inspect(ctx.getPointerArg(0).getByteArray(0, 0x100), " Unicorn hook hookUnicornBase64Encode");
}
}
}, module.base + 0xB372, module.base + 0xB376, null);
}
```

Run after writing the code

The first parameter of rsa is 32 bytes, that is, the last 32 bytes of 48 bytes of data randomly generated before, and the return value is 128 bytes

The first parameter of base64 is just the return value of the previous rsa

Use CyberChef website to verify whether it is a standard base64. The result is, as expected, the target

# last

rsa base64 is finished. The next article will analyze the zip + aes algorithm