See the question and my original answer on StackOverflow

You can use IImageList::GetOverlayImage method, here is a full sample:

static void Main()
{
    var info = new SHFILEINFO();
    SHGetFileInfo(@"c:\temp\my.lnk", FileAttributes.Normal, ref info, Marshal.SizeOf(info), SHGFI.SHGFI_ICON | SHGFI.SHGFI_OVERLAYINDEX);
    DestroyIcon(info.hIcon); // file + overlay, we don't need it

    // per doc: upper eight bits of the iIcon member 
    var overlayIndex = info.iIcon >> 24; // overlayIndex >= 1 and <= 15 (system limit)
    if (overlayIndex > 0)
    {
        // change size of required icon with SHIL parameter (JUMBO is 256x256)
        SHGetImageList(SHIL.SHIL_LARGE, typeof(IImageList).GUID, out var list);
        if (list != null)
        {
            list.GetOverlayImage(overlayIndex, out var imageIndex);
            if (imageIndex >= 0)
            {
                list.GetIcon(imageIndex, ILD.ILD_NORMAL, out var hicon);
                if (hicon != IntPtr.Zero)
                {
                    using (var bmp = Bitmap.FromHicon(hicon))
                    {
                        bmp.Save("Overlay" + overlayIndex + ".png");
                        DestroyIcon(hicon);
                    }
                }
            }
        }
    }
}

[DllImport("shell32", CharSet = CharSet.Unicode)]
public static extern IntPtr SHGetFileInfo(string pszPath, FileAttributes dwFileAttributes, ref SHFILEINFO psfi, int cbSizeFileInfo, SHGFI uFlags);

[DllImport("shell32")]
private static extern int SHGetImageList(SHIL iImageList, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IImageList ppv);

[DllImport("user32")]
public static extern bool DestroyIcon(IntPtr handle);


[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SHFILEINFO
{
    public IntPtr hIcon;
    public int iIcon;
    public int dwAttributes;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
    public string szDisplayName;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
    public string szTypeName;
}

public enum SHIL
{
    SHIL_LARGE = 0,
    SHIL_SMALL = 1,
    SHIL_EXTRALARGE = 2,
    SHIL_SYSSMALL = 3,
    SHIL_JUMBO = 4,
}

[Flags]
public enum ILD
{
    ILD_NORMAL = 0x00000000,
    ILD_TRANSPARENT = 0x00000001,
    ILD_MASK = 0x00000010,
    ILD_IMAGE = 0x00000020,
    ILD_ROP = 0x00000040,
    ILD_BLEND25 = 0x00000002,
    ILD_BLEND50 = 0x00000004,
    ILD_OVERLAYMASK = 0x00000F00,
    ILD_PRESERVEALPHA = 0x00001000,
    ILD_SCALE = 0x00002000,
    ILD_DPISCALE = 0x00004000,
    ILD_ASYNC = 0x00008000,
    ILD_SELECTED = ILD_BLEND50,
    ILD_FOCUS = ILD_BLEND25,
    ILD_BLEND = ILD_BLEND50,
}

[ComImport, Guid("46eb5926-582e-4017-9fdf-e8998daa0950"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public partial interface IImageList
{
    [PreserveSig]
    int Add(IntPtr hbmImage, IntPtr hbmMask, out int pi);

    [PreserveSig]
    int ReplaceIcon(int i, IntPtr hicon, out int pi);

    [PreserveSig]
    int SetOverlayImage(int iImage, int iOverlay);

    [PreserveSig]
    int Replace(int i, IntPtr hbmImage, IntPtr hbmMask);

    [PreserveSig]
    int AddMasked(IntPtr hbmImage, uint crMask, out int pi);

    [PreserveSig]
    int Draw(ref int pimldp);

    [PreserveSig]
    int Remove(int i);

    [PreserveSig]
    int GetIcon(int i, ILD flags, out IntPtr picon);

    [PreserveSig]
    int GetImageInfo(int i, out int pImageInfo);

    [PreserveSig]
    int Copy(int iDst, [MarshalAs(UnmanagedType.IUnknown)] object punkSrc, int iSrc, uint uFlags);

    [PreserveSig]
    int Merge(int i1, [MarshalAs(UnmanagedType.IUnknown)] object punk2, int i2, int dx, int dy, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv);

    [PreserveSig]
    int Clone([MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv);

    [PreserveSig]
    int GetImageRect(int i, IntPtr prc);

    [PreserveSig]
    int GetIconSize(out int cx, out int cy);

    [PreserveSig]
    int SetIconSize(int cx, int cy);

    [PreserveSig]
    int GetImageCount(out int pi);

    [PreserveSig]
    int SetImageCount(uint uNewCount);

    [PreserveSig]
    int SetBkColor(uint clrBk, out uint pclr);

    [PreserveSig]
    int GetBkColor(out uint pclr);

    [PreserveSig]
    int BeginDrag(int iTrack, int dxHotspot, int dyHotspot);

    [PreserveSig]
    int EndDrag();

    [PreserveSig]
    int DragEnter(IntPtr hwndLock, int x, int y);

    [PreserveSig]
    int DragLeave(IntPtr hwndLock);

    [PreserveSig]
    int DragMove(int x, int y);

    [PreserveSig]
    int SetDragCursorImage([MarshalAs(UnmanagedType.IUnknown)] object punk, int iDrag, int dxHotspot, int dyHotspot);

    [PreserveSig]
    int DragShowNolock(bool fShow);

    [PreserveSig]
    int GetDragImage(IntPtr ppt, IntPtr pptHotspot, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv);

    [PreserveSig]
    int GetItemFlags(int i, out uint dwFlags);

    [PreserveSig]
    int GetOverlayImage(int iOverlay, out int piIndex);
}

[Flags]
public enum SHGFI
{
    SHGFI_ICON = 0x000000100,
    SHGFI_DISPLAYNAME = 0x000000200,
    SHGFI_TYPENAME = 0x000000400,
    SHGFI_ATTRIBUTES = 0x000000800,
    SHGFI_ICONLOCATION = 0x000001000,
    SHGFI_EXETYPE = 0x000002000,
    SHGFI_SYSICONINDEX = 0x000004000,
    SHGFI_LINKOVERLAY = 0x000008000,
    SHGFI_SELECTED = 0x000010000,
    SHGFI_ATTR_SPECIFIED = 0x000020000,
    SHGFI_LARGEICON = 0x000000000,
    SHGFI_SMALLICON = 0x000000001,
    SHGFI_OPENICON = 0x000000002,
    SHGFI_SHELLICONSIZE = 0x000000004,
    SHGFI_PIDL = 0x000000008,
    SHGFI_USEFILEATTRIBUTES = 0x000000010,
    SHGFI_ADDOVERLAYS = 0x000000020,
    SHGFI_OVERLAYINDEX = 0x000000040,
}