go build
. File size - 7256576 bytes, DWARF in place. Will not work. Most often, with the release, all unnecessary is cut out from the binary. Standard utilities like strip do not work well with go, we find in Google one of the popular options for cutting a binary: go build -ldflags "-w -s"
. We look at what these flags do , find out that -w removes DWARF, and -s removes the symbol table and debugging information. We compile, we look at the file size - 4894720, well, it seems like no one promised what will be enough. lea rax, qword_452018+128h jmp rax
Go build ID: "e07bfb8669c13efb74574c0ad220c5f2cfae5cd4"
. We source golang sources, since they are available to us, and we find mention of this line. We notice a line in the linker code ctxt.Syms.Lookup("go.buildid", 0)
def go_find_pclntab(): pos = idaapi.get_segm_by_name(".text").endEA textstart = idaapi.get_segm_by_name(".text").startEA while True: # hex "go.buildid" , # gobuilddefpos = FindBinary( pos, SEARCH_UP, "67 45 23 01 " + "00 "*20 + "67 6f 2e 62 75 69 6c 64 69 64") if gobuilddefpos < 100 or gobuilddefpos > pos: # , # buildid pclntab entry :( break # buildid entry if Dword(gobuilddefpos-0x10) == textstart: # pclntab # pclntab return gobuilddefpos + 24 - Dword(gobuilddefpos-0x8) pos = gobuilddefpos return None def go_pclntab_travel(pclntab): nfunc = Dword(pclntab+8) # pclntab for i in xrange(nfunc): entry = pclntab + 0x10 + i * 0x10 sym = Qword(entry) info = Qword(entry + 8) + pclntab symnameoff = Dword(info + 8) + pclntab symname = GetString(symnameoff) # go_pclntab_handle_function(sym, symname, info)
type _type struct { size uintptr ptrdata uintptr // size of memory prefix holding all pointers hash uint32 tflag tflag align uint8 fieldalign uint8 kind uint8 alg *typeAlg // gcdata stores the GC type data for the garbage collector. // If the KindGCProg bit is set in kind, gcdata is a GC program. // Otherwise it is a ptrmask bitmap. See mbitmap.go for details. gcdata *byte str nameOff ptrToThis typeOff }
str nameOff
field. Hint: str is a string. Hint: nameOff β name β name β name of the type structure β name of the type. The type structure contains the type name! Only it is some kind of relative. We find out that str is the offset from the beginning of the types of the module section, a pointer to which can be obtained from the moduledata structure of the module. So in order to know the type, we need to find moduledata. For simplicity, we assume that we always have one module. We find in the runtime.resolveNameOff function that the first module is in the variable firstmoduledata, it must be found in our binary. To do this, you donβt need to go far, you can look at the same function resolveNameOff, because we already collected the addresses and names of all functions by the script above. It remains only to find the types for recognition, for this I simply took all the calls to the newobject function and took the pointers to the types from the parameters. lea rbx, _type_p_elliptic_p256Point_6dad60 ; *elliptic.p256Point mov [rsp+0A8h+var_A8], rbx call runtime_newobject ;
Source: https://habr.com/ru/post/325498/
All Articles