Binject / universal

Universal Shared Library User-space Loader
GNU General Public License v3.0
219 stars 26 forks source link

Can't load kernel32 in windows #3

Closed timwhitez closed 2 years ago

timwhitez commented 2 years ago
//go:build windows
// +build windows

package main

import (
    "github.com/Binject/universal"
    "io/ioutil"
    "log"
)

func main() {
    var image []byte
    var err error

    image, err = ioutil.ReadFile("C:\\windows\\system32\\kernel32.dll")

    loader, err := universal.NewLoader()
    if err != nil {
        log.Fatal(err)
    }

    library, err := loader.LoadLibrary("main", &image)
    if err != nil {
        log.Fatal(err)
    }

    val, err := library.Call("Sleep", 3000)
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("%+v\n", val)
}
awgh commented 2 years ago

kernel32 and ntdll are special cases because of how the Windows kernel works. You won't be able to load them with universal, but you also don't have to load them at all. They are already loaded in every process running on Windows.

You can access functions in kernel32 and ntdll using bananaphone (or at least the PEB-walking bits): https://github.com/C-Sto/BananaPhone

Look at the examples and the .S assembly files.

awgh commented 2 years ago

@timwhitez Here's the key bit: https://github.com/C-Sto/BananaPhone/blob/master/pkg/BananaPhone/asm_x64.s#L9

What's happening here... calls the GS register to read the location of the PEB, walks to the linked list of loaded images. Kernel32 is always the first one and NTDLL is always the second one. They're both always present in all Windows processes (as far as I know).

But just use syscall or bananaphone to call functions in kernel32/ntdll, they're both already there. No need to lazyload or use universal.

timwhitez commented 2 years ago

thanks, i try to use universal load 2nd ntdll to bypass some antivirus and it works :)

mmexport1640400844951

and Merry X'mas