myph~ shellcode loader for your evasion needs |
| git clone https://github.com/matro7sh/myph.git |
| log | files | refs | archive | README | LICENSE |
fromJson.go (8992B)
1 package rc 2 3 /* 4 Copied from : 5 https://github.com/tc-hib/go-winres/blob/main/resdir.go 6 7 and took just what we need. I left the data types as-is 8 if we want to expand usage later. 9 10 it would be really cool if this was just in the library, 11 but it might be actually, id have to check this out. 12 */ 13 14 import ( 15 "encoding/json" 16 "errors" 17 "image" 18 "os" 19 "path/filepath" 20 "sort" 21 "strconv" 22 "strings" 23 24 "github.com/tc-hib/winres" 25 "github.com/tc-hib/winres/version" 26 ) 27 28 const ( 29 errInvalidSet = "invalid resource set definition" 30 errInvalidCursor = "invalid cursor definition" 31 errInvalidIcon = "invalid icon definition" 32 ) 33 34 type jsonDef map[string]map[string]map[string]interface{} 35 36 var typeIDToString = map[winres.ID]string{ 37 winres.RT_CURSOR: "RT_CURSOR", 38 winres.RT_BITMAP: "RT_BITMAP", 39 winres.RT_ICON: "RT_ICON", 40 winres.RT_MENU: "RT_MENU", 41 winres.RT_DIALOG: "RT_DIALOG", 42 winres.RT_STRING: "RT_STRING", 43 winres.RT_FONTDIR: "RT_FONTDIR", 44 winres.RT_FONT: "RT_FONT", 45 winres.RT_ACCELERATOR: "RT_ACCELERATOR", 46 winres.RT_RCDATA: "RT_RCDATA", 47 winres.RT_MESSAGETABLE: "RT_MESSAGETABLE", 48 winres.RT_GROUP_CURSOR: "RT_GROUP_CURSOR", 49 winres.RT_GROUP_ICON: "RT_GROUP_ICON", 50 winres.RT_VERSION: "RT_VERSION", 51 winres.RT_PLUGPLAY: "RT_PLUGPLAY", 52 winres.RT_VXD: "RT_VXD", 53 winres.RT_ANICURSOR: "RT_ANICURSOR", 54 winres.RT_ANIICON: "RT_ANIICON", 55 winres.RT_HTML: "RT_HTML", 56 winres.RT_MANIFEST: "RT_MANIFEST", 57 } 58 59 var typeIDFromString = map[string]winres.ID{ 60 "RT_CURSOR": winres.RT_CURSOR, 61 "RT_BITMAP": winres.RT_BITMAP, 62 "RT_ICON": winres.RT_ICON, 63 "RT_MENU": winres.RT_MENU, 64 "RT_DIALOG": winres.RT_DIALOG, 65 "RT_STRING": winres.RT_STRING, 66 "RT_FONTDIR": winres.RT_FONTDIR, 67 "RT_FONT": winres.RT_FONT, 68 "RT_ACCELERATOR": winres.RT_ACCELERATOR, 69 "RT_RCDATA": winres.RT_RCDATA, 70 "RT_MESSAGETABLE": winres.RT_MESSAGETABLE, 71 "RT_GROUP_CURSOR": winres.RT_GROUP_CURSOR, 72 "RT_GROUP_ICON": winres.RT_GROUP_ICON, 73 "RT_VERSION": winres.RT_VERSION, 74 "RT_PLUGPLAY": winres.RT_PLUGPLAY, 75 "RT_VXD": winres.RT_VXD, 76 "RT_ANICURSOR": winres.RT_ANICURSOR, 77 "RT_ANIICON": winres.RT_ANIICON, 78 "RT_HTML": winres.RT_HTML, 79 "RT_MANIFEST": winres.RT_MANIFEST, 80 } 81 82 func idsFromStrings(t, r, l string) (winres.Identifier, winres.Identifier, uint16, error) { 83 var ( 84 typeID winres.Identifier 85 resID winres.Identifier 86 langID uint16 87 ) 88 89 if id, ok := typeIDFromString[t]; ok { 90 typeID = id 91 } else { 92 typeID = stringToIdentifier(t) 93 } 94 if typeID == nil { 95 return nil, nil, 0, errors.New("invalid type identifier") 96 } 97 98 resID = stringToIdentifier(r) 99 if resID == nil { 100 return nil, nil, 0, errors.New("invalid resource identifier") 101 } 102 103 n, err := strconv.ParseUint(l, 16, 16) 104 if err != nil { 105 return nil, nil, 0, errors.New("invalid language identifier") 106 } 107 langID = uint16(n) 108 109 return typeID, resID, langID, nil 110 } 111 112 func stringToIdentifier(s string) winres.Identifier { 113 if s == "" { 114 return nil 115 } 116 if s[0] == '#' { 117 n, err := strconv.ParseInt(s[1:], 10, 16) 118 if err == nil { 119 return winres.ID(n) 120 } 121 } 122 return winres.Name(s) 123 } 124 125 func LoadResourcesFromJson(rs *winres.ResourceSet, jsonName string) error { 126 dir := filepath.Dir(jsonName) 127 b, err := os.ReadFile(jsonName) 128 129 if err != nil { 130 return err 131 } 132 res := jsonDef{} 133 err = json.Unmarshal(b, &res) 134 if err != nil { 135 return err 136 } 137 138 for tid, t := range res { 139 for _, r := range sortedRes(t) { 140 for _, l := range sortedLang(r.langs) { 141 typeID, resID, langID, err := idsFromStrings(tid, r.id, l.id) 142 if err != nil { 143 return err 144 } 145 switch typeID { 146 case winres.RT_ICON: 147 return errors.New("cannot import RT_ICON resources directly, use RT_GROUP_ICON instead") 148 case winres.RT_CURSOR: 149 return errors.New("cannot import RT_CURSOR resources directly, use RT_GROUP_CURSOR instead") 150 case winres.RT_GROUP_CURSOR: 151 cursor, err := loadCursor(dir, l.data) 152 if err != nil { 153 return err 154 } 155 err = rs.SetCursorTranslation(resID, langID, cursor) 156 if err != nil { 157 return err 158 } 159 case winres.RT_GROUP_ICON: 160 icon, err := loadIcon(dir, l.data) 161 if err != nil { 162 return err 163 } 164 err = rs.SetIconTranslation(resID, langID, icon) 165 if err != nil { 166 return err 167 } 168 case winres.RT_VERSION: 169 vi := version.Info{} 170 j, _ := json.Marshal(l.data) 171 err = json.Unmarshal(j, &vi) 172 if err != nil { 173 return err 174 } 175 rs.SetVersionInfo(vi) 176 case winres.RT_BITMAP: 177 filename, ok := l.data.(string) 178 if !ok { 179 return errors.New(errInvalidSet) 180 } 181 dib, err := loadBMP(filepath.Join(dir, filename)) 182 if err != nil { 183 return err 184 } 185 err = rs.Set(winres.RT_BITMAP, resID, langID, dib) 186 if err != nil { 187 return err 188 } 189 case winres.RT_MANIFEST: 190 switch val := l.data.(type) { 191 case string: 192 data, err := os.ReadFile(filepath.Join(dir, val)) 193 if err != nil { 194 return err 195 } 196 err = rs.Set(typeID, resID, langID, data) 197 if err != nil { 198 return err 199 } 200 default: 201 j, _ := json.Marshal(val) 202 m := winres.AppManifest{} 203 err = json.Unmarshal(j, &m) 204 if err != nil { 205 return err 206 } 207 rs.SetManifest(m) 208 } 209 default: 210 filename, ok := l.data.(string) 211 if !ok { 212 return errors.New(errInvalidSet) 213 } 214 data, err := os.ReadFile(filepath.Join(dir, filename)) 215 if err != nil { 216 return err 217 } 218 err = rs.Set(typeID, resID, langID, data) 219 if err != nil { 220 return err 221 } 222 } 223 } 224 } 225 } 226 227 return nil 228 } 229 230 type resource struct { 231 id string 232 langs map[string]interface{} 233 } 234 235 type lang struct { 236 id string 237 data interface{} 238 } 239 240 func sortedRes(m map[string]map[string]interface{}) []resource { 241 var res []resource 242 for id, langs := range m { 243 res = append(res, resource{id, langs}) 244 } 245 sort.Slice(res, func(i, j int) bool { 246 return res[i].id < res[j].id 247 }) 248 return res 249 } 250 251 func sortedLang(m map[string]interface{}) []lang { 252 var l []lang 253 for id, data := range m { 254 l = append(l, lang{id, data}) 255 } 256 sort.Slice(l, func(i, j int) bool { 257 return l[i].id < l[j].id 258 }) 259 return l 260 } 261 262 func loadCursor(dir string, c interface{}) (*winres.Cursor, error) { 263 switch c := c.(type) { 264 case string: 265 return loadCUR(filepath.Join(dir, c)) 266 267 case []interface{}: 268 var images []winres.CursorImage 269 for i := range c { 270 o, ok := c[i].(map[string]interface{}) 271 if !ok { 272 return nil, errors.New(errInvalidCursor) 273 } 274 curImg, err := loadCursorImage(dir, o) 275 if err != nil { 276 return nil, err 277 } 278 images = append(images, curImg) 279 } 280 return winres.NewCursorFromImages(images) 281 282 case map[string]interface{}: 283 curImg, err := loadCursorImage(dir, c) 284 if err != nil { 285 return nil, err 286 } 287 return winres.NewCursorFromImages([]winres.CursorImage{curImg}) 288 } 289 290 return nil, errors.New(errInvalidCursor) 291 } 292 293 func loadCursorImage(dir string, c map[string]interface{}) (winres.CursorImage, error) { 294 x, xOK := c["x"].(float64) 295 y, yOK := c["y"].(float64) 296 f, fOK := c["image"].(string) 297 if !fOK || !xOK || !yOK { 298 return winres.CursorImage{}, errors.New(errInvalidCursor) 299 } 300 301 img, err := loadImage(filepath.Join(dir, f)) 302 if err != nil { 303 return winres.CursorImage{}, err 304 } 305 306 return winres.CursorImage{ 307 Image: img, 308 HotSpot: winres.HotSpot{X: uint16(x), Y: uint16(y)}, 309 }, nil 310 } 311 312 func loadIcon(dir string, x interface{}) (*winres.Icon, error) { 313 switch x := x.(type) { 314 case string: 315 if strings.ToLower(filepath.Ext(x)) == ".ico" { 316 return loadICO(filepath.Join(dir, x)) 317 } 318 img, err := loadImage(filepath.Join(dir, x)) 319 if err != nil { 320 return nil, err 321 } 322 return winres.NewIconFromResizedImage(img, nil) 323 case []interface{}: 324 var images []image.Image 325 for i := range x { 326 f, ok := x[i].(string) 327 if !ok { 328 return nil, errors.New(errInvalidIcon) 329 } 330 img, err := loadImage(filepath.Join(dir, f)) 331 if err != nil { 332 return nil, err 333 } 334 images = append(images, img) 335 } 336 return winres.NewIconFromImages(images) 337 } 338 return nil, errors.New(errInvalidIcon) 339 } 340 341 func loadImage(name string) (image.Image, error) { 342 f, err := os.Open(name) 343 if err != nil { 344 return nil, err 345 } 346 defer f.Close() 347 348 img, _, err := image.Decode(f) 349 return img, err 350 } 351 352 func loadCUR(name string) (*winres.Cursor, error) { 353 f, err := os.Open(name) 354 if err != nil { 355 return nil, err 356 } 357 defer f.Close() 358 359 return winres.LoadCUR(f) 360 } 361 362 func loadICO(name string) (*winres.Icon, error) { 363 f, err := os.Open(name) 364 if err != nil { 365 return nil, err 366 } 367 defer f.Close() 368 369 return winres.LoadICO(f) 370 } 371 372 func loadBMP(name string) ([]byte, error) { 373 b, err := os.ReadFile(name) 374 if err != nil { 375 return nil, err 376 } 377 378 if len(b) > 14 && b[0] == 'B' && b[1] == 'M' && int(b[5])<<24|int(b[4])<<16|int(b[3])<<8|int(b[2]) == len(b) { 379 return b[14:], nil 380 } 381 382 return b, nil 383 }