I can get the HICON with ExtractIconW
for example:
package main
import (
"log"
"syscall"
"unsafe"
)
func MakeIntResource(id uintptr) *uint16 {
return (*uint16)(unsafe.Pointer(id))
}
const IDI_QUESTION = 32514
func main() {
user32Dll := syscall.NewLazyDLL("User32.dll")
procLoadIconW := user32Dll.NewProc("LoadIconW")
hIcon, _, _ := syscall.SyscallN(procLoadIconW.Addr(),
0, uintptr(unsafe.Pointer(MakeIntResource(IDI_QUESTION))),
)
log.Println(hIcon)
}
But I don't know what I should do next to save HICON as a file (bitmap format is enough).
A real .ico file usually contains multiple images of different sizes while a HICON is just a single image.
If the goal is to copy the original icon then you must LoadLibraryEx as a datafile and then use the resource functions to first find the RT_GROUP_ICON and once you have that you know the RT_ICON ids and you can extract the sub-images and write your .ico.
If you still think you want to save a HICON, call GetIconInfo to get the image.
There are no low-level Windows functions to write .ico files. You can try GDI+ or WIC or write them yourself. The file format is very close to the resource format (stores a file offset instead of a resource id).
A guide to Windows icon formats starts here...
The following code is an example which writing by go, and it saves one of the resources to a bitmap file.
// Step:
// get HICON
// get ICONINFO from HICON
// get Bitmap from ICONINFO
// save Bitmap to a File
// Note: To make the example look simple, I ignore all possible errors handling.
func Example_saveFileIconAsBitmap() {
user32dll := w32.NewUser32DLL()
kernel32dll := w32.NewKernel32DLL()
gdi32dll := w32.NewGdi32DLL()
var hIcon w32.HICON
{
// Because I already know the iconID(myResourceID) I want, I can load it directly.
// If you want to find the appropriate iconID after searching through RT_GROUP_ICON you can refer to this example:
// https://github.com/CarsonSlovoka/go-pkg/blob/34e5d2c1fc97bf149bf626acaaf8773fe1509d64/v2/w32/kernel32_func_test.go#L331-L353
hmExe := kernel32dll.LoadLibrary("./testdata/exe/writeWithFont.exe") // writeWithFont.exe is in here: https://github.com/CarsonSlovoka/go-pkg/tree/983a2c1/v2/w32/testdata/exe
myResourceID := uintptr(1) // You can use resourceHacker.exe to help you find the ID.
hRes, _ := kernel32dll.FindResource(hmExe,
w32.MakeIntResource(myResourceID),
w32.MakeIntResource(w32.RT_ICON),
)
hMem, _ := kernel32dll.LoadResource(hmExe, hRes)
lpResource := kernel32dll.LockResource(hMem)
hIcon = user32dll.CreateIconFromResourceEx(lpResource,
kernel32dll.MustSizeofResource(hmExe, hRes), true, 0x00030000,
32, 32, // size X, Y
w32.LR_DEFAULTCOLOR,
)
}
var iInfo w32.ICONINFO
{
if !user32dll.GetIconInfo(hIcon, &iInfo) {
return
}
// Remember to release when you are not using the HBITMAP.
defer func() {
_ = gdi32dll.DeleteObject(w32.HGDIOBJ(iInfo.HbmColor))
_ = gdi32dll.DeleteObject(w32.HGDIOBJ(iInfo.HbmMask))
}()
}
bmp := w32.Bitmap{}
{
// Create BITMAP by ICONINFO
gdi32dll.GetObject(w32.HANDLE(iInfo.HbmColor), int32(unsafe.Sizeof(bmp)), uintptr(unsafe.Pointer(&bmp)))
}
// Save Bitmap to a file.
var (
bitmapFileHeader w32.BitmapFileHeader // https://en.wikipedia.org/wiki/BMP_file_format#Bitmap_file_header
bitmapInfoHeader w32.BitmapInfoHeader // https://en.wikipedia.org/wiki/BMP_file_format#DIB_header_(bitmap_information_header)
)
{
bitmapInfoHeader = w32.BitmapInfoHeader{
Size: uint32(unsafe.Sizeof(bitmapInfoHeader)), // 40
Width: bmp.Width, Height: bmp.Height,
Planes: 1,
BitCount: 32,
Compression: w32.BI_RGB,
}
bmpSize := ((bmp.Width*int32(bitmapInfoHeader.BitCount) + 31) / 32) * 4 /* uint32 */ * bmp.Height // see the wiki: https://en.wikipedia.org/wiki/BMP_file_format#Pixel_storage
sizeofDIB := 14 + uint32(unsafe.Sizeof(bitmapInfoHeader)) + uint32(bmpSize)
bitmapFileHeader = w32.BitmapFileHeader{
Type: 0x4D42, // BM. // B: 42, M: 4D // All of the integer values are stored in little-endian format
Size: sizeofDIB, // HEADER + INFO + DATA
OffsetBits: 14 + uint32(unsafe.Sizeof(bitmapInfoHeader)),
}
hdc := user32dll.GetDC(0)
var lpBitmap w32.LPVOID
hDIB, _ := kernel32dll.GlobalAlloc(w32.GHND, w32.SIZE_T(bmpSize))
lpBitmap, _ = kernel32dll.GlobalLock(hDIB)
defer func() {
kernel32dll.GlobalUnlock(hDIB)
kernel32dll.GlobalFree(hDIB)
}()
gdi32dll.GetDIBits(
hdc, iInfo.HbmColor,
0,
w32.UINT(bmp.Height),
lpBitmap, // [out]
&w32.BitmapInfo{Header: bitmapInfoHeader},
w32.DIB_RGB_COLORS,
)
outputBmpPath := "testdata/temp001.bmp"
// Write: FileHeader, DIPHeader, bitmapData
{
f, _ := os.Create(outputBmpPath)
defer func() {
_ = os.Remove(outputBmpPath) // Remove test data. If you want to see the result, delete this line to see the final data.
}()
// FileHeader
_ = binary.Write(f, binary.LittleEndian, bitmapFileHeader)
// DIP Header
_ = binary.Write(f, binary.LittleEndian, bitmapInfoHeader)
// bitmapData
bmpDatas := make([]byte, sizeofDIB)
var offset uint32 = 0
for offset = 0; offset < sizeofDIB; offset += 1 {
curByteAddr := unsafe.Pointer(uintptr(lpBitmap) + uintptr(offset))
bmpDatas[offset] = *(*byte)(curByteAddr)
}
_ = binary.Write(f, binary.LittleEndian, bmpDatas)
_ = f.Close()
}
}
// Output:
}
Above code is part of a third-party library, but no other third-party resources are used.
It is no longer written as a single file because winapi has too many constants, variables, and types, and the declaration of the DLL is also very tedious.
If you are interested, you can download this library back. Its packaging is very simple. If you do not like to use other third parties to capture the relevant variables can be done.
The following pictures will help you understand the meaning of the parameters of MAKEINTRESOURCE more easily.
Related
I am trying to patch a chunk of memory in Golang. I have the VirtualProtect functionality down and the memory chunk is being changed to RW, but I can't find figure out the Golang functionality for Copying into memory.
I want to emulate this from a Powershell Script:
[System.Runtime.InteropServices.Marshal]::Copy($patch, 0, $targetedAddress, 3)
The Golang code I currently have is below:
var patch = []byte {
0x31, 0xC0, // xor rax, rax
0xC3, // ret
}
var oldfperms uint32
virtualProt(unsafe.Pointer(&patchAddr), unsafe.Sizeof(uintptr(2)), uint32(0x40),
unsafe.Pointer(&oldfperms)) // Modify region for ReadWrite
var r uintptr
for _, b := range patch {
r = (r << 8) | uintptr(b)
}
patch := unsafe.Pointer(uintptr(r)) // Attempting to copy into memory here and I'm stumped
fmt.Println(patch)
var a uint32
virtualProt(unsafe.Pointer(&patchAddr), unsafe.Sizeof(uintptr(2)), oldfperms, unsafe.Pointer(&a)) // Change region back to normal
Nevermind. Found the reference to the Win32 WriteProcessMemory function and used that.
https://pkg.go.dev/github.com/0xrawsec/golang-win32/win32/kernel32#WriteProcessMemory
func WriteProcMem(currProccess uintptr, patchAddr uintptr, patch uintptr) bool {
kern32WriteMem := syscall.NewLazyDLL("kernel32.dll").NewProc("WriteProcessMemory")
_, _, _ = kern32WriteMem.Call(
currProccess,
patchAddr,
patch)
fmt.Println("[+] Patched Memory!")
return true
}
I'm using golang to call a Dll function like char* fn(), the dll is not written by myself and I cannot change it. Here's my code:
package main
import (
"fmt"
"syscall"
"unsafe"
)
func main() {
dll := syscall.MustLoadDLL("my.dll")
fn := dll.MustFindProc("fn")
r, _, _ := fn.Call()
p := (*byte)(unsafe.Pointer(r))
// define a slice to fill with the p string
data := make([]byte, 0)
// loop until find '\0'
for *p != 0 {
data = append(data, *p) // append 1 byte
r += unsafe.Sizeof(byte(0)) // move r to next byte
p = (*byte)(unsafe.Pointer(r)) // get the byte value
}
name := string(data) // convert to Golang string
fmt.Println(name)
}
I have some questions:
Is there any better way of doing this? There're hundred of dll functions like this, I'll have to write the loop for all functions.
For very-long-string like 100k+ bytes, will append() cause performance issue?
Solved. the unsafe.Pointer(r) causes linter govet shows warning possible misuse of unsafe.Pointer, but the code runs fine, how to avoid this warning? Solution: This can be solved by adding -unsafeptr=false to govet command line, for vim-ale, add let g:ale_go_govet_options = '-unsafeptr=false'.
Casting uintptr as upointer is haram.
You must read the rules:
https://golang.org/pkg/unsafe/#Pointer
But there's hacky way, that shouldn't produce warning:
//go:linkname gostringn runtime.gostringn
func gostringn(p uintptr, l int) string
//go:linkname findnull runtime.findnull
//go:nosplit
func findnull(s uintptr) int
// ....
name := gostringn(r, findnull(r))
Functions takes pointer, but we link them from runtime as uintptr because they have same sizeof.
Might work in theory. But is also frowned upon.
Getting back to your code, as JimB said, you could do it one line with:
name := C.GoString((*C.char)(unsafe.Pointer(r)))
I got the following solution by tracking the os.Args of the go source code, But I am based on go1.17. If you are in another version, you can read the source code to solve it.
func UintPtrToString(r uintptr) string {
p := (*uint16)(unsafe.Pointer(r))
if p == nil {
return ""
}
n, end, add := 0, unsafe.Pointer(p), unsafe.Sizeof(*p)
for *(*uint16)(end) != 0 {
end = unsafe.Add(end, add)
n++
}
return string(utf16.Decode(unsafe.Slice(p, n)))
}
I'm trying to call procedure (without name) from a DLL using the ordinal value.
I can use this DLL in C#, setting the ordinal value to the property EntryPoint of DllImport.
... or you can identify the entry point by its ordinal. Ordinals are prefixed with the # sign, for example, #1. [...]
Example in C#:
[DllImport("dllname.dll", EntryPoint = "#3", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
public static extern int DeviceList(ref IntPtr hDeviceList);
When try find the procedure with "#" sign in Go, it shows the the following error:
Failed to find #3 procedure in dllname.dll: The specified procedure could not be found.
I used dumpbin to show the information of the DLL, no function has a name:
Is there a way to find a procedure with its ordinal value (like C#)?
There is a github issue here for this, but it seems not to have been merged as of Go 1.10.3 (the version I am using right now).
Anyway, the github issue links to a changeset with the respective function from which I extracted the code to do what you want here:
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
procGetProcAddress = kernel32.NewProc("GetProcAddress")
)
// GetProcAddressByOrdinal retrieves the address of the exported
// function from module by ordinal.
func GetProcAddressByOrdinal(module syscall.Handle, ordinal uintptr) (uintptr, error) {
r0, _, _ := syscall.Syscall(procGetProcAddress.Addr(), 2, uintptr(module), ordinal, 0)
proc := uintptr(r0)
if proc == 0 {
return 0, syscall.EINVAL
}
return proc, nil
}
For completeness, here is the full example with which I tested this, using the Dependecy Walker I found that the first function in kernel32.dll is AcquireSRWLockExclusive and using the new function it shows that the proc addresses really match.
package main
import (
"fmt"
"syscall"
)
func main() {
dll, err := syscall.LoadDLL("kernel32.dll")
check(err)
want, err := syscall.GetProcAddress(dll.Handle, "AcquireSRWLockExclusive")
check(err)
fmt.Println(want)
first, err := GetProcAddressByOrdinal(dll.Handle, 1)
check(err)
fmt.Println(first)
}
func check(err error) {
if err != nil {
panic(err)
}
}
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
procGetProcAddress = kernel32.NewProc("GetProcAddress")
)
// GetProcAddressByOrdinal retrieves the address of the exported
// function from module by ordinal.
func GetProcAddressByOrdinal(module syscall.Handle, ordinal uintptr) (uintptr, error) {
r0, _, _ := syscall.Syscall(procGetProcAddress.Addr(), 2, uintptr(module), ordinal, 0)
proc := uintptr(r0)
if proc == 0 {
return 0, syscall.EINVAL
}
return proc, nil
}
I want to create a tool with Go that lets me resize multiple windows on my screen. As an example lets assume that I want to find my Firefox window and my Atom (text editor) window and place them, so that they take up exactly half of my screen (FF left, Atom right).
So far I realized, that I need to use the Windows API for that. I created a method that gives me all handles and the titles of all windows, but I'm struggling with geometry information. I understand that the api call GetWindowRect will help, but how can I get the information out of a pointer to a rect?
Follow up question 1: what other information can I get about the windows?
Follow up question 2: How do I resize the window so that it takes exactly half my screen size? I guess, I need another call to get the monitor dimensions.
What I have so far is the code below. The main program finds all handles and displays those containing 'Atom' in the title. The windows package contains the code accessing the windows API.
My current result is that I get 2 handles for atom (why not just 1?). I guess, I have to learn more about the Windows API, too. Are there good summaries to understand the basics?
main.go:
package main
import (
"resizer/windows"
"fmt"
"log"
"strings"
)
func main() {
const title = "Atom"
m := windows.GetAllWindows()
fmt.Printf("Map of windows: \n")
for handle := range m {
if strings.Contains(m[handle].Title(), title) {
fmt.Printf("'%v'\n", m[handle])
}
}
}
windows.go:
package windows
import (
"fmt"
"log"
"syscall"
"unsafe"
)
var (
user32 = syscall.MustLoadDLL("user32.dll")
procEnumWindows = user32.MustFindProc("EnumWindows")
procGetWindowTextW = user32.MustFindProc("GetWindowTextW")
)
// Window represents any Window that is opened in the Windows OS
type Window struct {
handle syscall.Handle
title string
}
// Title returns the title of the window
func (w Window) Title() string {
return w.title
}
// GetAllWindows finds all currently opened windows
func GetAllWindows() map[syscall.Handle]Window {
m := make(map[syscall.Handle]Window)
cb := syscall.NewCallback(func(h syscall.Handle, p uintptr) uintptr {
bytes := make([]uint16, 200)
_, err := GetWindowText(h, &bytes[0], int32(len(bytes)))
title := "||| no title found |||"
if err == nil {
title = syscall.UTF16ToString(bytes)
}
m[h] = Window{h, title}
return 1 // continue enumeration
})
EnumWindows(cb, 0)
return m
}
// EnumWindows loops through all windows and calls a callback function on each
func EnumWindows(enumFunc uintptr, lparam uintptr) (err error) {
r1, _, e1 := syscall.Syscall(procEnumWindows.Addr(), 2, uintptr(enumFunc), uintptr(lparam), 0)
if r1 == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
// GetWindowText gets the title of a Window given by a certain handle
func GetWindowText(hwnd syscall.Handle, str *uint16, maxCount int32) (len int32, err error) {
r0, _, e1 := syscall.Syscall(procGetWindowTextW.Addr(), 3, uintptr(hwnd), uintptr(unsafe.Pointer(str)), uintptr(maxCount))
len = int32(r0)
if len == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
GetWindowRect() writes the geometry to the RECT structure you pass the pointer to in. It operates exactly like the GetWindowText() call you already have; the difference is you have to provide the RECT structure yourself.
You should be able to just get away with copying the structure verbatim. To substitute data types, use this page. The definition for RECT says all the fields are LONG, which that page says is "[a] 32-bit signed integer". So this should suffice:
type RECT struct {
left int32 // or Left, Top, etc. if this type is to be exported
top int32
right int32
bottom int32
}
(Most likely irrelevant, but it's worth pointing out that RECT operates identically to image.Rectangle, with left and top being Min and right and bottom being Max. They are not identical because image.Rectangle uses int, so you may want to consider providing conversion functions if you want to use image's geometry functions to manipulate rectangles instead of GDI's.)
I'm working in Go 1.6 on Windows and trying to export a certificate container to a PFX (the ultimate goal here is to access an exportable private key from the certificate store).
I have opened a memory store and inserted a certificate into the store:
var storedCertCtx *syscall.CertContext
storeHandle, err := syscall.CertOpenStore(syscall.CERT_STORE_PROV_MEMORY, 0, 0, syscall.CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, 0)
err = syscall.CertAddCertificateContextToStore(storeHandle, certenum, syscall.CERT_STORE_ADD_ALWAYS, &storedCertCtx)
Now I want to generate a PFX of that store. I have defined a struct for containing the data blob and want to use PFXExportCertStoreEx to get a PFX of the store:
var (
crypt32 = syscall.NewLazyDLL("crypt32.dll")
procPFXExportCertStoreEx = crypt32.NewProc("PFXExportCertStoreEx")
)
type CRYPTOAPI_BLOB struct {
DataSize uint32
Data *byte
}
var pfxBlob CRYPTOAPI_BLOB
err = PfxExportCertStore(storeHandle, &pfxBlob, syscall.StringToUTF16Ptr("MyPassword"), 0, 0)
syscall.Syscall6(procPFXExportCertStoreEx.Addr(), 5,
uintptr(storeHandle), //hStore
uintptr(unsafe.Pointer(&pfxBlob)), //*pPFX
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("password"))), //szPassword
0, //*pvPara
0, //dwFlags
0)
And this half works.
DataSize is populated with what looks like an appropriate value (i.e. if I add more certificates to the store, it grows bigger), however Data is always <nil>.
Seeing as it's meant to be populated with a pointer, I have tried declaring it as *uintptr and uint32 (just to see if anything gets populated), but nothing. The value is always untouched (if I manually put junk data in there, the junk data stays after the syscall is executed).
Have I defined the struct incorrectly? There is precious few examples to go for getting this done in Go, but from what I can see from the numerous C examples, this should be working.
This is the expected behavior.
According to this: https://msdn.microsoft.com/en-us/library/windows/desktop/aa387313(v=vs.85).aspx, the pPFX struct requires a pre-allocated buffer, with the size in the cbData field, which will be updated with the size of the data copied in.
If the call is made with pbData equal to NULL, only the cbData field is updated to reflect the size needed for the output buffer.
JimB's answer is most certainly correct, but I want to add this for followup in case anyone else is going down this path. The actual code that I had to use to get the PFX file into CRYPTOAPI_BLOB was:
var (
crypt32 = syscall.NewLazyDLL("crypt32.dll")
procPFXExportCertStoreEx = crypt32.NewProc("PFXExportCertStoreEx")
procCryptMemAlloc = crypt32.NewProc("CryptMemAlloc")
procCryptMemFree = crypt32.NewProc("CryptMemFree")
)
type CRYPTOAPI_BLOB struct {
cbData uint32
pbData *byte
}
func (b *CRYPTOAPI_BLOB) ToByteArray() []byte {
d := make([]byte, b.cbData)
copy(d, (*[1 << 30]byte)(unsafe.Pointer(b.pbData))[:])
return d
}
func PfxExportCertStore(storeHandle syscall.Handle, password string, flags uint32) (returnData []byte, err error) {
var pfxBlob CRYPTOAPI_BLOB
r1, _, _ := syscall.Syscall6(procPFXExportCertStoreEx.Addr(), 5,
uintptr(storeHandle), //hStore
uintptr(unsafe.Pointer(&pfxBlob)), //*pPFX
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(password))), //szPassword
0, //*pvPara
uintptr(flags), //dwFlags
0)
r2, _, _ := syscall.Syscall(procCryptMemAlloc.Addr(), 1, uintptr(unsafe.Pointer(&pfxBlob.cbData)), 0, 0)
p := unsafe.Pointer(&r2)
q := (*byte)(p)
pfxBlob.pbData = q
defer syscall.Syscall(procCryptMemFree.Addr(), 1, uintptr(unsafe.Pointer(pfxBlob.pbData)), 0, 0)
r3, _, _ := syscall.Syscall6(procPFXExportCertStoreEx.Addr(), 5,
uintptr(storeHandle), //hStore
uintptr(unsafe.Pointer(&pfxBlob)), //*pPFX
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(password))), //szPassword
0, //*pvPara
uintptr(flags), //dwFlags
0)
returnData = pfxBlob.ToByteArray()
return
}
(I have stripped the error handling to make it easier to read). The first call to PFXExportCertStoreEx just returns the size, and once we have the size we can do a call to PFXExportCertStoreEx to allocate a buffer, and then we pass the same pointer to PFXExportCertStoreEx, but this time it has the allocated buffer, and we get the full PFX file returned.