Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

Resigning a signed assembly

5.00/5 (5 votes)
18 Dec 2012CPOL 22K   483  
In this project we learn how to resign a signed assembly with another one of your choice

Introduction 

Signing a .net assembly is the best way to secure your assemblies from being modified (cracked), and there is a project that describes how to remove the signature of the assembly: 

Remove signing from assembly 

But i didn't found any code that can resign a signed assembly, so if i modified an assembly (using a hex editor), i will be able to resign it (with another key surely) in order to use it signed. 

Image 1

Using the code

Construtors

VB
Public Sub New(ByVal assembly As String, ByVal snk As Byte())
    _strAssemblyPath = assembly
    _bytSNKFile = snk
End Sub

Public Sub New(ByVal assembly As String, ByVal snk As String)
    _strAssemblyPath = assembly
    _bytSNKFile = IO.File.ReadAllBytes(snk)
End Sub 

Global declarations

VB.NET
Private _bytAssembly As Byte()
Private _bytAssemblyPublicKey As Byte()

Private _bytSNKFile As Byte()
Private _strAssemblyPath As String

Private _strNewStrongKeyName As String
Private csRandom As Random = New Random(Environment.TickCount) 

We need to use some API functions:

VB.NET
<DllImport("MsCorEE.dll", EntryPoint:="StrongNameFreeBuffer", CharSet:=CharSet.Auto)> _
Private Shared Sub StrongNameFreeBuffer(ByVal pbMemory As IntPtr)
End Sub

<DllImport("MsCorEE.dll", EntryPoint:="StrongNameKeyDelete", CharSet:=CharSet.Auto)> _
Private Shared Function StrongNameKeyDelete(ByVal wszKeyContainer As String) As Boolean
End Function

<DllImport("MsCorEE.dll", EntryPoint:="StrongNameKeyInstall", CharSet:=CharSet.Auto)> _
Private Shared Function StrongNameKeyInstall( _
        <MarshalAs(UnmanagedType.LPWStr)> ByVal wszKeyContainer As String, _
        <MarshalAs(UnmanagedType.LPArray, SizeParamIndex:=2, SizeConst:=0)> ByVal pbKeyBlob As Byte(), _
        ByVal cbKeyBlob As Integer) As Boolean
End Function

<DllImport("MsCorEE.dll", EntryPoint:="StrongNameErrorInfo", CharSet:=CharSet.Auto)> _
Private Shared Function StrongNameErrorInfo() As UInt32
End Function

<DllImport("MsCorEE.dll", EntryPoint:="StrongNameSignatureGeneration", CharSet:=CharSet.Auto)> _
Private Shared Function StrongNameSignatureGeneration( _
        ByVal wszFilePath As String, _
        ByVal wszKeyContainer As String, _
        ByVal pbKeyBlob As Integer, _
        ByVal cbKeyBlob As Integer, _
        ByVal ppbSignatureBlob As Integer, _
        ByVal pcbSignatureBlob As Integer) As Boolean
End Function

<DllImport("MsCorEE.dll", EntryPoint:="StrongNameTokenFromAssemblyEx", CharSet:=CharSet.Auto)> _
Private Shared Function StrongNameTokenFromAssemblyEx( _
        ByVal wszFilePath As String, _
        <Out()> ByRef ppbStrongNameToken As IntPtr, _
        <Out()> ByRef pcbStrongNameToken As ULong, _
        ByRef ppbPublicKeyBlob As IntPtr, _
        ByRef pcbPublicKeyBlob As ULong) As Boolean
End Function 

And the main code will consist of the following two functions:

VB.NET
Private Function CheckForPubliKeyIndex(ByVal intIndex1 As Integer) As Boolean
    Dim intIndex2 As Integer
    Do
        If _bytAssemblyPublicKey(intIndex2) <> _bytAssembly(intIndex2 + intIndex1) Then Return False
        intIndex2 += 1
    Loop While (intIndex2 < _bytAssemblyPublicKey.Length)
    Return True
End Function

Public Function Resign() As Boolean
 
    Dim bytSNK As Byte()
    Dim blnReturn As Boolean
    Dim strSNKFile As String = ""

    Try
        strSNKFile = My.Computer.FileSystem.GetTempFileName
        IO.File.WriteAllBytes(strSNKFile, _bytSNKFile)

        Using keyPairFile As FileStream = File.OpenRead(strSNKFile)
            bytSNK = New StrongNameKeyPair(keyPairFile).PublicKey
            keyPairFile.Close()
        End Using

        _bytAssemblyPublicKey = AssemblyName.GetAssemblyName(_strAssemblyPath).GetPublicKey

        If _bytAssemblyPublicKey Is Nothing Then Exit Try

        Using csFileStream As FileStream = File.OpenRead(_strAssemblyPath)
            _bytAssembly = New Byte(csFileStream.Length - 1) {}
            csFileStream.Read(_bytAssembly, 0, csFileStream.Length)
            csFileStream.Close()
        End Using
 
        Dim intAssemblyPublicKeyIndex As Byte = _bytAssemblyPublicKey(0)
        Dim intCounter As Integer
        Dim intPublicKeyIndex As Integer

        Do
            If ((_bytAssembly(intCounter) = intAssemblyPublicKeyIndex) _
                    AndAlso Me.CheckForPubliKeyIndex(intCounter)) Then
                intPublicKeyIndex = intCounter
                Exit Do
            End If
            intCounter += 1
        Loop While (intCounter < Me._bytAssembly.Length)

        Dim num4 As Integer

        Do
            _bytAssembly((intPublicKeyIndex + num4)) = bytSNK(num4)
            num4 += 1
        Loop While (num4 < bytSNK.Length)

        Using csFileStream As FileStream = File.Create(Me._strAssemblyPath)
            csFileStream.Write(_bytAssembly, 0, Me._bytAssembly.Length)
            csFileStream.Close()
        End Using
 
        Me._strNewStrongKeyName = String.Format("{0}-{1}", _
            Me.csRandom.Next(&H989680, &H5F5E0FF).ToString, _
            Me.csRandom.Next(&H989680, &H5F5E0FF).ToString)

        StrongNameKeyDelete(Me._strNewStrongKeyName)

        Using input As New FileStream(strSNKFile, FileMode.Open, FileAccess.Read)
            Using reader As New BinaryReader(input)

                Dim buffer2 As Byte() = New Byte(CInt(reader.BaseStream.Length) - 1) {}
                reader.BaseStream.Seek(0, SeekOrigin.Begin)
                reader.Read(buffer2, 0, CInt(reader.BaseStream.Length))

                Dim length As Integer = CInt(reader.BaseStream.Length)
                reader.Close()
                input.Close()

                If Not StrongNameKeyInstall(Me._strNewStrongKeyName, buffer2, length) Then
                    ' Failed to sign the assembly
                ElseIf StrongNameSignatureGeneration(Me._strAssemblyPath, Me._strNewStrongKeyName, 0, 0, 0, 0) Then
                    blnReturn = True
                Else
                    ' Failed to sign the assembly
                End If

            End Using
        End Using

    Catch exc As Exception
        ' blnReturn = False ' MsgBox(exc.Message)
    Finally
        IO.File.Delete(strSNKFile)
    End Try

    Return blnReturn

End Function 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)