github.com/google/osv-scalibr@v0.4.1/detector/weakcredentials/winlocal/samreg/domainf_test.go (about)

     1  // Copyright 2025 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package samreg
    16  
    17  import (
    18  	"slices"
    19  	"strings"
    20  	"testing"
    21  )
    22  
    23  func TestDomainFDeriveSyskey(t *testing.T) {
    24  	tests := []struct {
    25  		name        string
    26  		syskey      []byte
    27  		buffer      []byte
    28  		want        []byte
    29  		wantErr     bool
    30  		wantErrText string
    31  	}{
    32  		{
    33  			name:   "derivation_RC4_succeeds",
    34  			syskey: []byte("\x88\x93\xae\x93\x45\x13\xbd\xdd\x25\x47\x35\x16\x3e\x9d\x33\x00"),
    35  			buffer: []byte("\x02\x00\x01\x00\x00\x00\x00\x00\x40\x15\x3b\x97\x46\x9f\xce\x01\x26\x00\x00\x00\x00\x00\x00\x00\x00\x80\xa6\x0a\xff\xde\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\xcc\x1d\xcf\xfb\xff\xff\xff\x00\xcc\x1d\xcf\xfb\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xe9\x03\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x38\x00\x00\x00\x23\x7e\xe9\x12\xa7\x34\xbf\x93\x18\x6e\xaa\xc1\x83\x07\x59\xa1\xd6\x96\xa6\x99\x6b\xa9\x41\x61\x44\x92\xb0\xfb\xd0\x0a\xe9\xa6\x37\xd6\x7c\xc6\x99\x2b\xc7\x12\xfe\x22\xa0\x17\x71\xce\xd3\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x38\x00\x00\x00\x3d\xfe\xe0\xd7\x20\xeb\x39\xc1\x44\x1c\x8d\x05\x29\xd6\x83\x47\x92\xa2\x29\x38\xfc\x9e\xa7\x29\xa9\x36\x7d\x4a\xfc\x6c\xe1\xb3\xd3\xac\xd4\xac\xe2\x5b\xab\xf9\xf8\x3f\x09\xe1\x91\x1a\x7d\xda\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00"),
    36  			want:   []byte("\x3d\x21\x2c\xe8\xa2\xda\x83\x43\xbd\xad\x1e\xf2\xcf\xb6\xb3\x1c"),
    37  		},
    38  		{
    39  			name:   "derivation_AES_succeeds",
    40  			syskey: []byte("\x95\x60\xbf\x6a\x47\xe0\xc9\x02\xb0\x82\x45\xf1\x96\xd5\x4e\x4f"),
    41  			buffer: []byte("\x03\x00\x01\x00\x00\x00\x00\x00\x7d\xdc\xe4\xd7\xae\x0a\xdb\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x80\xa6\x0a\xff\xde\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x44\x5f\x9a\xfe\xff\xff\xff\x00\x44\x5f\x9a\xfe\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xea\x03\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x00\x00\x00\x70\x00\x00\x00\x30\x00\x00\x00\x20\x00\x00\x00\x69\xcc\x39\x99\xf8\xc2\x32\xee\x75\x6e\xfe\x19\xe5\x52\xfd\x7f\xdf\x24\xbb\x41\xd5\x88\x39\x31\x28\x60\x6e\x96\x0f\x0d\x9c\xc1\x86\x40\xd1\x41\x5b\x0a\x0b\x74\x36\xae\xcd\xcf\xb9\x64\xe1\x1d\xbb\x2c\x3a\x60\xf9\xab\x0e\x36\x02\xe6\x29\x24\x54\xed\xfa\x0e\xf3\xbe\x13\xbd\x24\x0a\x9c\x96\xca\xeb\xcc\x6c\x18\x19\x3e\x57\xb8\x51\x80\x81\x2a\x13\xe3\x1c\x76\x11\xd2\x47\x43\xaa\x10\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x70\x00\x00\x00\x30\x00\x00\x00\x20\x00\x00\x00\x17\xf1\xdf\x69\x49\x14\xce\x2b\xae\xa0\xf6\x6b\x79\x2f\xb3\x90\x9d\x08\x11\xbe\x24\xed\x58\x2a\x18\x60\xb3\x51\x63\x73\xd2\x3d\x88\x7c\xd5\x11\x17\x2c\xdc\x80\xa3\x32\x14\xd3\x4a\x08\xf5\x91\x5e\x47\xc2\xb4\x8f\x09\x4a\x7b\xd6\x37\x1b\xa9\xd1\x9a\x77\x05\xb0\xb7\x4f\xe0\xa8\xeb\x5b\xb6\x82\xfb\x00\x44\xd1\x13\xf6\x31\x57\xf2\x2f\xb8\x61\x67\x60\x4e\x63\x6a\xed\x83\x0c\x72\x55\x69\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00"),
    42  			want:   []byte("\xfc\xde\xe8\x3a\xc6\xc1\x4b\x28\xf5\x26\x50\x1f\xc6\xe8\xbb\xc3"),
    43  		},
    44  		{
    45  			name:        "domainF_too_short_RC4_returns_error",
    46  			buffer:      []byte("A"),
    47  			wantErr:     true,
    48  			wantErrText: errDomainFTooShort.Error(),
    49  		},
    50  		{
    51  			name:        "domainF_too_short_AES_returns_error",
    52  			buffer:      []byte(strings.Repeat("A", fDomStructKeyOffset) + "\x02" + strings.Repeat("A", 32)),
    53  			wantErr:     true,
    54  			wantErrText: errDomainFTooShort.Error(),
    55  		},
    56  		{
    57  			name:        "invalid_RC4_checksum_returns_error",
    58  			syskey:      []byte("\x88\x93\xae\x93\x45\x13\xbd\xdd\x25\x47\x34\x16\x3e\x9d\x33\x00"),
    59  			buffer:      []byte("\x02\x00\x01\x00\x00\x00\x00\x00\x40\x15\x3b\x97\x46\x9f\xce\x01\x26\x00\x00\x00\x00\x00\x00\x00\x00\x80\xa6\x0a\xff\xde\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\xcc\x1d\xcf\xfb\xff\xff\xff\x00\xcc\x1d\xcf\xfb\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xe9\x03\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x38\x00\x00\x00\x23\x7e\xe9\x12\xa7\x34\xbf\x93\x18\x6e\xaa\xc1\x83\x07\x59\xa1\xd6\x96\xa6\x99\x6b\xa9\x41\x61\x44\x92\xb0\xfb\xd0\x0a\xe9\xa6\x37\xd6\x7c\xc6\x99\x2b\xc7\x12\xfe\x22\xa0\x17\x71\xce\xd3\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x38\x00\x00\x00\x3d\xfe\xe0\xd7\x20\xeb\x39\xc1\x44\x1c\x8d\x05\x29\xd6\x83\x47\x92\xa2\x29\x38\xfc\x9e\xa7\x29\xa9\x36\x7d\x4a\xfc\x6c\xe1\xb3\xd3\xac\xd4\xac\xe2\x5b\xab\xf9\xf8\x3f\x09\xe1\x91\x1a\x7d\xda\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00"),
    60  			wantErr:     true,
    61  			wantErrText: errInvalidChecksum.Error(),
    62  		},
    63  		{
    64  			name:        "invalid_revision_returns_error",
    65  			buffer:      []byte(strings.Repeat("A", fDomStructKeyOffset) + "\xFF"),
    66  			wantErr:     true,
    67  			wantErrText: errInvalidRevision.Error(),
    68  		},
    69  		{
    70  			name:        "decode_syskey_RC4_failure_returns_error",
    71  			buffer:      []byte(strings.Repeat("A", fDomStructKeyOffset) + "\x01"),
    72  			wantErr:     true,
    73  			wantErrText: "unexpected EOF",
    74  		},
    75  		{
    76  			name:        "decode_syskey_AES_failure_returns_error",
    77  			buffer:      []byte(strings.Repeat("A", fDomStructKeyOffset) + "\x02"),
    78  			wantErr:     true,
    79  			wantErrText: "unexpected EOF",
    80  		},
    81  		{
    82  			name:        "missing_syskey_AES_returns_error",
    83  			syskey:      []byte(""),
    84  			buffer:      []byte(strings.Repeat("\x00", fDomStructKeyOffset) + "\x02" + strings.Repeat("\x00", 0xCC)),
    85  			wantErr:     true,
    86  			wantErrText: "crypto/aes: invalid key size 0",
    87  		},
    88  	}
    89  
    90  	for _, tc := range tests {
    91  		t.Run(tc.name, func(t *testing.T) {
    92  			got, gotErr := newDomainF(tc.buffer).DeriveSyskey(tc.syskey)
    93  			if (gotErr != nil) != tc.wantErr {
    94  				t.Errorf("DeriveSyskey(...): unexpected error: %v", gotErr)
    95  			}
    96  
    97  			if tc.wantErr {
    98  				if !strings.Contains(gotErr.Error(), tc.wantErrText) {
    99  					t.Errorf("DeriveSyskey(...): unexpected error, got: %v, want: %v", gotErr, tc.wantErrText)
   100  				}
   101  
   102  				return
   103  			}
   104  
   105  			if !slices.Equal(got, tc.want) {
   106  				t.Errorf("DeriveSyskey(...): got %x, want %x", got, tc.want)
   107  			}
   108  		})
   109  	}
   110  }