pastebin - collaborative debugging tool
nrubsig.kpaste.net RSS

Difference between
modified post 97daa63 by Anonymous on Sat 25th May 2024 11:00
original post 3da241c by Anonymous on Fri 24th May 2024 16:30
Download diff
Show old version | new version | both versions

    
11
22
/*
33
 * MIT License
44
 *
55
 * Copyright (c) 2024 Roland Mainz <roland.mainz@nrubsig.org>
66
 *
77
 * Permission is hereby granted, free of charge, to any person obtaining a copy
88
 * of this software and associated documentation files (the "Software"), to deal
99
 * in the Software without restriction, including without limitation the rights
1010
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1111
 * copies of the Software, and to permit persons to whom the Software is
1212
 * furnished to do so, subject to the following conditions:
1313
 *
1414
 * The above copyright notice and this permission notice shall be included in all
1515
 * copies or substantial portions of the Software.
1616
 *
1717
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1818
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1919
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2020
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2121
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2222
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2323
 * SOFTWARE.
2424
 */
2525
2626
/*
2727
 * winsg.c - run Win32 or Cygwin program with a different (primary) group
2828
 *
2929
 * Written by Roland Mainz <roland.mainz@nrubsig.org>
3030
 */
3131
3232
/*
3333
 * Compile with:
3434
 * $ clang -target x86_64-pc-windows-gnu -Wall -DUNICODE=1 -D_UNICODE=1 -g winsg.c -o winsg.exe #
3535
 */
3636
3737
#include <windows.h>
3838
#include <stdio.h>
3939
#include <stdbool.h>
4040
#include <assert.h>
4141
#include <Lmcons.h>
4242
#include <process.h>
4343
4444
#if 0
4545
#define D(x) x
4646
#else
4747
#define D(x)
4848
#endif
4949
5050
#ifdef _WIN64
5151
#define CYGWIN_BASH_PATH "C:\\cygwin64\\bin\\bash.exe"
5252
#else
5353
#define CYGWIN_BASH_PATH "C:\\cygwin\\bin\\bash.exe"
5454
#endif /* _WIN64 */
5555
#define WIN32_CMDEXE_PATH "C:\\Windows\\system32\\cmd.exe"
5656
5757
/*
58+
 * DECLARE_SID_BUFFER - declare a buffer for a SID value
5867
 * Performance hack:
5968
 * GETTOKINFO_EXTRA_BUFFER - extra space for more data
6069
 * |GetTokenInformation()| for |TOKEN_USER| and |TOKEN_PRIMARY_GROUP|
6170
 * always fails in Win10 with |ERROR_INSUFFICIENT_BUFFER| if you
6271
 * just pass the |sizeof(TOKEN_*)| value. Instead of calling
6372
 * |GetTokenInformation()| with |NULL| arg to obtain the size to
6473
 * allocate we just provide 2048 bytes of extra space after the
6574
 * |TOKEN_*| size, and pray it is enough
6675
 */
6776
#define GETTOKINFO_EXTRA_BUFFER (2048)
6877
6978
D(
7079
static
7180
bool get_token_primarygroup_name(HANDLE tok, char *out_buffer)
7281
{
7382
    DWORD tokdatalen;
7483
    PTOKEN_PRIMARY_GROUP ptpgroup;
7584
    PSID pgsid;
7685
    DWORD namesize = GNLEN+1;
7786
    char domainbuffer[UNLEN+1];
7887
    DWORD domainbuffer_size = sizeof(domainbuffer);
7988
    SID_NAME_USE name_use;
8089
8190
    tokdatalen = sizeof(TOKEN_PRIMARY_GROUP)+GETTOKINFO_EXTRA_BUFFER;
8291
    ptpgroup = _alloca(tokdatalen);
8392
    if (!GetTokenInformation(tok, TokenPrimaryGroup, ptpgroup,
8493
        tokdatalen, &tokdatalen)) {
8594
        D((void)fprintf(stderr, "get_token_primarygroup_name: "
8695
            "GetTokenInformation(tok=0x%p, TokenPrimaryGroup) failed, "
8796
            "status=%d.\n",
8897
            (void *)tok, (int)GetLastError()));
8998
        return false;
9099
    }
91100
92101
    pgsid = ptpgroup->PrimaryGroup;
93102
94103
    if (!LookupAccountSidA(NULL, pgsid, out_buffer, &namesize,
95104
        domainbuffer, &domainbuffer_size, &name_use)) {
96105
        D((void)fprintf(stderr, "get_token_primarygroup_name: "
97106
            "LookupAccountSidA() failed, status=%d.\n",
98107
            (int)GetLastError()));
99108
        return false;
100109
    }
101110
102111
    return true;
103112
}
104113
)
105114
106115
static
107116
bool is_group_in_token(HANDLE tok, PSID qsid)
108117
{
109118
    DWORD tokdatalen;
110119
    PTOKEN_GROUPS ptgroups;
111120
112121
    tokdatalen = sizeof(TOKEN_GROUPS)+GETTOKINFO_EXTRA_BUFFER;
113122
    ptgroups = _alloca(tokdatalen);
114123
    if (!GetTokenInformation(tok, TokenGroups, ptgroups,
115124
        tokdatalen, &tokdatalen)) {
116125
        D((void)fprintf(stderr, "is_group_in_token: "
117126
            "GetTokenInformation(tok=0x%p, TokenGroups) failed, "
118127
            "status=%d.\n",
119128
            (void *)tok, (int)GetLastError()));
120129
        return false;
121130
    }
122131
123132
    int i;
124133
    D(
125134
        (void)fprintf(stderr, "is_group_in_token: got %d groups\n",
126135
            (int)ptgroups->GroupCount)
127136
    );
128137
    for (i = 0 ; i < ptgroups->GroupCount ; i++) {
129138
        if (EqualSid(qsid, ptgroups->Groups[i].Sid) &&
130139
            (ptgroups->Groups[i].Attributes & SE_GROUP_ENABLED)) {
131140
            D((void)puts("is_group_in_token: #match"));
132141
            return true;
133142
        }
134143
    }
135144
136145
    D((void)puts("is_group_in_token: #no match"));
137146
138147
    return false;
139148
}
140149
141150
static
142151
bool get_group_sid(const char *groupname, PSID pgsid, PDWORD pgsid_size)
143152
{
144153
    char domainbuffer[UNLEN+1];
145154
    DWORD domainbuffer_size = sizeof(domainbuffer);
146155
    SID_NAME_USE name_use;
147156
148157
    if (!LookupAccountNameA(NULL, groupname,
149158
        pgsid, pgsid_size, domainbuffer, &domainbuffer_size, &name_use)) {
150159
        D((void)fprintf(stderr, "get_group_sid: "
151160
            "LookupAccountNameA() failed.\n"));
152161
        return false;
153162
    }
154163
155164
    return true;
156165
}
157166
158167
static
159168
bool set_token_primarygroup_sid(HANDLE tok, PSID pgsid)
160169
{
161170
    DWORD tokdatalen;
162171
    TOKEN_PRIMARY_GROUP tpgroup;
163172
164173
    tokdatalen = sizeof(TOKEN_PRIMARY_GROUP);
165174
    tpgroup.PrimaryGroup = pgsid;
166175
    if (!SetTokenInformation(tok, TokenPrimaryGroup,
167176
        &tpgroup, tokdatalen)) {
168177
        D((void)fprintf(stderr, "set_token_primarygroup_sid: "
169178
            "SetTokenInformation(tok=0x%p, TokenPrimaryGroup) failed, "
170179
            "status=%d\n",
171180
            (void *)tok, (int)GetLastError()));
172181
        return false;
173182
    }
174183
175184
    return true;
176185
}
177186
178187
static
179-
char *stpcpy (char *s1, const char *s2)
188+
char *stpcpy (char *restrict s1, const char *restrict s2)
180189
{
181190
    size_t l = strlen(s2);
182191
    return memcpy(s1, s2, l+1) + l;
183192
}
184193
185194
static
186195
void win32cmd_quotearg(char *s1, const char *s2)
187196
{
188197
    int c;
189198
    *s1++ = '"';
190199
    while ((c = *s2) != '\0') {
191200
        switch(c) {
192201
            case '"':
193202
                *s1++='\\';
194203
                *s1 = c;
195204
                break;
196205
            default:
197206
                *s1 = c;
198207
                break;
199208
        }
200209
        s1++;
201210
        s2++;
202211
    }
203212
    *s1++ = '"';
204213
    *s1 = '\0';
205214
}
206215
207-
216+
static
208-
enum shelltype {
217+
int usage(void)
216218
{
217-
    enum shelltype st = SHELLTYPE_NOT_SET;
219+
    (void)fprintf(stderr, "Usage: "
218-
    int cmd_arg_index = -1;
220+
        "winsg [-] -g group [-c command | /C command]]\n"
219-
    const char *newgrpname = NULL;
221+
        "Execute command as different primary group ID\n"
220-
    HANDLE tok = INVALID_HANDLE_VALUE;
222+
        "\n"
221-
    int subcmdret = EXIT_FAILURE;
223+
        "Examples:\n"
222-
    int retval = 1;
224+
        "\t1. Run new cmd.exe with primary group 'abc1':\n"
223-
    int i;
225+
        "\t\twinsg -g abc1 /C\n"
224-
226+
        "\n"
225-
    for (i=1 ; i < ac ; i++) {
227+
        "\t2. Run new Cygwin bash with primary group 'abc2':\n"
226-
        D((void)fprintf(stderr, "# i=%d, av[i]='%s'\n", i, av[i]));
228+
        "\t\twinsg -g abc2 /C\n"
227-
229+
        "\n"
228-
        if (!strcmp(av[i], "-")) {
230+
        "\t3. Start /bin/id from cmd.exe with primary group 'abc3':\n"
229-
            (void)fprintf(stderr, "%s: "
231+
        "\t\twinsg abc3 /C 'C:\\cygwin64\\bin\\id.exe -a'\n"
230-
                "Run in new login not supported yet.\n", av[0]);
232+
        "\n"
231-
            retval = 1;
233+
        "\t4. Start /bin/id from Cygwin bash with primary group "
232-
            goto done;
234+
            "'abc4':\n"
235+
        "\t\twinsg abc4 -c '/bin/id.exe -a'\n"
233241
        }
242+

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at