Skip to content

Commit 5e8b12a

Browse files
authored
Merge pull request #19955 from MathiasVP/flow-through-create-thread
C++: Add flow summaries for `CreateThread` and friends
2 parents c10d899 + e610498 commit 5e8b12a

File tree

5 files changed

+212
-16
lines changed

5 files changed

+212
-16
lines changed

cpp/ql/lib/ext/Windows.model.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,8 @@ extensions:
3232
- ["", "", False, "CommandLineToArgvA", "", "", "Argument[*0]", "ReturnValue[**]", "taint", "manual"]
3333
- ["", "", False, "CommandLineToArgvW", "", "", "Argument[*0]", "ReturnValue[**]", "taint", "manual"]
3434
# fileapi.h
35-
- ["", "", False, "ReadFileEx", "", "", "Argument[*3].Field[@hEvent]", "Argument[4].Parameter[*2].Field[@hEvent]", "value", "manual"]
35+
- ["", "", False, "ReadFileEx", "", "", "Argument[*3].Field[@hEvent]", "Argument[4].Parameter[*2].Field[@hEvent]", "value", "manual"]
36+
# processthreadsapi.h
37+
- ["", "", False, "CreateThread", "", "", "Argument[@3]", "Argument[2].Parameter[@0]", "value", "manual"]
38+
- ["", "", False, "CreateRemoteThread", "", "", "Argument[@4]", "Argument[3].Parameter[@0]", "value", "manual"]
39+
- ["", "", False, "CreateRemoteThreadEx", "", "", "Argument[@4]", "Argument[3].Parameter[@0]", "value", "manual"]
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Added flow models for the Win32 API functions `CreateThread`, `CreateRemoteThread`, and `CreateRemoteThreadEx`.

cpp/ql/test/library-tests/dataflow/external-models/flow.expected

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@ models
1717
| 16 | Source: ; ; false; ymlSource; ; ; ReturnValue; local; manual |
1818
| 17 | Source: boost::asio; ; false; read_until; ; ; Argument[*1]; remote; manual |
1919
| 18 | Summary: ; ; false; CommandLineToArgvA; ; ; Argument[*0]; ReturnValue[**]; taint; manual |
20-
| 19 | Summary: ; ; false; ReadFileEx; ; ; Argument[*3].Field[@hEvent]; Argument[4].Parameter[*2].Field[@hEvent]; value; manual |
21-
| 20 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
22-
| 21 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
23-
| 22 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
24-
| 23 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
20+
| 19 | Summary: ; ; false; CreateRemoteThread; ; ; Argument[@4]; Argument[3].Parameter[@0]; value; manual |
21+
| 20 | Summary: ; ; false; CreateRemoteThreadEx; ; ; Argument[@4]; Argument[3].Parameter[@0]; value; manual |
22+
| 21 | Summary: ; ; false; CreateThread; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual |
23+
| 22 | Summary: ; ; false; ReadFileEx; ; ; Argument[*3].Field[@hEvent]; Argument[4].Parameter[*2].Field[@hEvent]; value; manual |
24+
| 23 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
25+
| 24 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
26+
| 25 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
27+
| 26 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
2528
edges
26-
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:23 |
29+
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:26 |
2730
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:17 |
2831
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | *recv_buffer | provenance | Src:MaD:17 Sink:MaD:2 |
2932
| asio_streams.cpp:97:37:97:44 | call to source | asio_streams.cpp:98:7:98:14 | send_str | provenance | TaintFunction |
@@ -32,10 +35,10 @@ edges
3235
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | |
3336
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:2 |
3437
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | provenance | |
35-
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:23 |
36-
| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:21 |
37-
| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:20 |
38-
| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:22 |
38+
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:26 |
39+
| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:24 |
40+
| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:23 |
41+
| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:25 |
3942
| test.cpp:7:47:7:52 | value2 | test.cpp:7:64:7:69 | value2 | provenance | |
4043
| test.cpp:7:64:7:69 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | provenance | |
4144
| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:10:10:10:18 | call to ymlSource | provenance | Src:MaD:16 |
@@ -47,15 +50,15 @@ edges
4750
| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | |
4851
| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:18:10:18:10 | y | provenance | Sink:MaD:1 |
4952
| test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | provenance | |
50-
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:21 |
53+
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:24 |
5154
| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | |
5255
| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:22:10:22:10 | z | provenance | Sink:MaD:1 |
5356
| test.cpp:21:27:21:27 | x | test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | provenance | |
54-
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:20 |
57+
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:23 |
5558
| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | |
5659
| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:26:10:26:11 | y2 | provenance | Sink:MaD:1 |
5760
| test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | provenance | |
58-
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:22 |
61+
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:25 |
5962
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | provenance | |
6063
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:33:10:33:11 | z2 | provenance | Sink:MaD:1 |
6164
| test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | provenance | |
@@ -73,8 +76,8 @@ edges
7376
| windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | windows.cpp:41:10:41:13 | * ... | provenance | Src:MaD:5 |
7477
| windows.cpp:90:6:90:15 | [summary param] *3 in ReadFileEx [*hEvent] | windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[*hEvent] in ReadFileEx | provenance | |
7578
| windows.cpp:90:6:90:15 | [summary param] *3 in ReadFileEx [hEvent] | windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[hEvent] in ReadFileEx | provenance | |
76-
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[*hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[*hEvent] in ReadFileEx | provenance | MaD:19 |
77-
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[hEvent] in ReadFileEx | provenance | MaD:19 |
79+
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[*hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[*hEvent] in ReadFileEx | provenance | MaD:22 |
80+
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[hEvent] in ReadFileEx | provenance | MaD:22 |
7881
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [*hEvent] | windows.cpp:147:16:147:27 | *lpOverlapped [*hEvent] | provenance | |
7982
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [hEvent] | windows.cpp:157:16:157:27 | *lpOverlapped [hEvent] | provenance | |
8083
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[*hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [*hEvent] | provenance | |
@@ -122,6 +125,29 @@ edges
122125
| windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | provenance | Src:MaD:12 |
123126
| windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | windows.cpp:333:20:333:52 | *pMapView | provenance | |
124127
| windows.cpp:333:20:333:52 | *pMapView | windows.cpp:335:10:335:16 | * ... | provenance | |
128+
| windows.cpp:349:8:349:19 | [summary param] *3 in CreateThread [x] | windows.cpp:349:8:349:19 | [summary] to write: Argument[2].Parameter[*0] in CreateThread [x] | provenance | MaD:21 |
129+
| windows.cpp:349:8:349:19 | [summary] to write: Argument[2].Parameter[*0] in CreateThread [x] | windows.cpp:403:26:403:36 | *lpParameter [x] | provenance | |
130+
| windows.cpp:357:8:357:25 | [summary param] *4 in CreateRemoteThread [x] | windows.cpp:357:8:357:25 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThread [x] | provenance | MaD:19 |
131+
| windows.cpp:357:8:357:25 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThread [x] | windows.cpp:410:26:410:36 | *lpParameter [x] | provenance | |
132+
| windows.cpp:387:8:387:27 | [summary param] *4 in CreateRemoteThreadEx [x] | windows.cpp:387:8:387:27 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThreadEx [x] | provenance | MaD:20 |
133+
| windows.cpp:387:8:387:27 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThreadEx [x] | windows.cpp:417:26:417:36 | *lpParameter [x] | provenance | |
134+
| windows.cpp:403:26:403:36 | *lpParameter [x] | windows.cpp:405:10:405:25 | *lpParameter [x] | provenance | |
135+
| windows.cpp:405:10:405:25 | *lpParameter [x] | windows.cpp:406:8:406:8 | *s [x] | provenance | |
136+
| windows.cpp:406:8:406:8 | *s [x] | windows.cpp:406:8:406:11 | x | provenance | |
137+
| windows.cpp:410:26:410:36 | *lpParameter [x] | windows.cpp:412:10:412:25 | *lpParameter [x] | provenance | |
138+
| windows.cpp:412:10:412:25 | *lpParameter [x] | windows.cpp:413:8:413:8 | *s [x] | provenance | |
139+
| windows.cpp:413:8:413:8 | *s [x] | windows.cpp:413:8:413:11 | x | provenance | |
140+
| windows.cpp:417:26:417:36 | *lpParameter [x] | windows.cpp:419:10:419:25 | *lpParameter [x] | provenance | |
141+
| windows.cpp:419:10:419:25 | *lpParameter [x] | windows.cpp:420:8:420:8 | *s [x] | provenance | |
142+
| windows.cpp:420:8:420:8 | *s [x] | windows.cpp:420:8:420:11 | x | provenance | |
143+
| windows.cpp:431:3:431:3 | *s [post update] [x] | windows.cpp:439:7:439:8 | *& ... [x] | provenance | |
144+
| windows.cpp:431:3:431:3 | *s [post update] [x] | windows.cpp:451:7:451:8 | *& ... [x] | provenance | |
145+
| windows.cpp:431:3:431:3 | *s [post update] [x] | windows.cpp:464:7:464:8 | *& ... [x] | provenance | |
146+
| windows.cpp:431:3:431:16 | ... = ... | windows.cpp:431:3:431:3 | *s [post update] [x] | provenance | |
147+
| windows.cpp:431:9:431:14 | call to source | windows.cpp:431:3:431:16 | ... = ... | provenance | |
148+
| windows.cpp:439:7:439:8 | *& ... [x] | windows.cpp:349:8:349:19 | [summary param] *3 in CreateThread [x] | provenance | |
149+
| windows.cpp:451:7:451:8 | *& ... [x] | windows.cpp:357:8:357:25 | [summary param] *4 in CreateRemoteThread [x] | provenance | |
150+
| windows.cpp:464:7:464:8 | *& ... [x] | windows.cpp:387:8:387:27 | [summary param] *4 in CreateRemoteThreadEx [x] | provenance | |
125151
nodes
126152
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | semmle.label | [summary param] *0 in buffer |
127153
| asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | semmle.label | [summary] to write: ReturnValue in buffer |
@@ -238,6 +264,30 @@ nodes
238264
| windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | semmle.label | *call to MapViewOfFileNuma2 |
239265
| windows.cpp:333:20:333:52 | *pMapView | semmle.label | *pMapView |
240266
| windows.cpp:335:10:335:16 | * ... | semmle.label | * ... |
267+
| windows.cpp:349:8:349:19 | [summary param] *3 in CreateThread [x] | semmle.label | [summary param] *3 in CreateThread [x] |
268+
| windows.cpp:349:8:349:19 | [summary] to write: Argument[2].Parameter[*0] in CreateThread [x] | semmle.label | [summary] to write: Argument[2].Parameter[*0] in CreateThread [x] |
269+
| windows.cpp:357:8:357:25 | [summary param] *4 in CreateRemoteThread [x] | semmle.label | [summary param] *4 in CreateRemoteThread [x] |
270+
| windows.cpp:357:8:357:25 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThread [x] | semmle.label | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThread [x] |
271+
| windows.cpp:387:8:387:27 | [summary param] *4 in CreateRemoteThreadEx [x] | semmle.label | [summary param] *4 in CreateRemoteThreadEx [x] |
272+
| windows.cpp:387:8:387:27 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThreadEx [x] | semmle.label | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThreadEx [x] |
273+
| windows.cpp:403:26:403:36 | *lpParameter [x] | semmle.label | *lpParameter [x] |
274+
| windows.cpp:405:10:405:25 | *lpParameter [x] | semmle.label | *lpParameter [x] |
275+
| windows.cpp:406:8:406:8 | *s [x] | semmle.label | *s [x] |
276+
| windows.cpp:406:8:406:11 | x | semmle.label | x |
277+
| windows.cpp:410:26:410:36 | *lpParameter [x] | semmle.label | *lpParameter [x] |
278+
| windows.cpp:412:10:412:25 | *lpParameter [x] | semmle.label | *lpParameter [x] |
279+
| windows.cpp:413:8:413:8 | *s [x] | semmle.label | *s [x] |
280+
| windows.cpp:413:8:413:11 | x | semmle.label | x |
281+
| windows.cpp:417:26:417:36 | *lpParameter [x] | semmle.label | *lpParameter [x] |
282+
| windows.cpp:419:10:419:25 | *lpParameter [x] | semmle.label | *lpParameter [x] |
283+
| windows.cpp:420:8:420:8 | *s [x] | semmle.label | *s [x] |
284+
| windows.cpp:420:8:420:11 | x | semmle.label | x |
285+
| windows.cpp:431:3:431:3 | *s [post update] [x] | semmle.label | *s [post update] [x] |
286+
| windows.cpp:431:3:431:16 | ... = ... | semmle.label | ... = ... |
287+
| windows.cpp:431:9:431:14 | call to source | semmle.label | call to source |
288+
| windows.cpp:439:7:439:8 | *& ... [x] | semmle.label | *& ... [x] |
289+
| windows.cpp:451:7:451:8 | *& ... [x] | semmle.label | *& ... [x] |
290+
| windows.cpp:464:7:464:8 | *& ... [x] | semmle.label | *& ... [x] |
241291
subpaths
242292
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | asio_streams.cpp:100:44:100:62 | call to buffer |
243293
| test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual |

cpp/ql/test/library-tests/dataflow/external-models/validatemodels.expected

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4638,7 +4638,13 @@
46384638
| Dubious signature "(z_streamp,int *)" in summary model. |
46394639
| Dubious signature "(z_streamp,unsigned int *,int *)" in summary model. |
46404640
| Dubious signature "(z_streamp,unsigned int)" in summary model. |
4641+
| Unrecognized input specification "Argument[***3]" in summary model. |
4642+
| Unrecognized input specification "Argument[***4]" in summary model. |
4643+
| Unrecognized input specification "Argument[****3]" in summary model. |
4644+
| Unrecognized input specification "Argument[****4]" in summary model. |
46414645
| Unrecognized input specification "Field[****hEvent]" in summary model. |
46424646
| Unrecognized input specification "Field[***hEvent]" in summary model. |
46434647
| Unrecognized output specification "Field[****hEvent]" in summary model. |
46444648
| Unrecognized output specification "Field[***hEvent]" in summary model. |
4649+
| Unrecognized output specification "Parameter[***0]" in summary model. |
4650+
| Unrecognized output specification "Parameter[****0]" in summary model. |

cpp/ql/test/library-tests/dataflow/external-models/windows.cpp

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,3 +335,135 @@ void mapViewOfFile(HANDLE hMapFile) {
335335
sink(*buffer); // $ ir
336336
}
337337
}
338+
339+
typedef struct _SECURITY_ATTRIBUTES
340+
{
341+
DWORD nLength;
342+
LPVOID lpSecurityDescriptor;
343+
BOOL bInheritHandle;
344+
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
345+
346+
typedef DWORD (*LPTHREAD_START_ROUTINE)(
347+
LPVOID lpThreadParameter);
348+
349+
HANDLE CreateThread(
350+
LPSECURITY_ATTRIBUTES lpThreadAttributes,
351+
SIZE_T dwStackSize,
352+
LPTHREAD_START_ROUTINE lpStartAddress,
353+
LPVOID lpParameter,
354+
DWORD dwCreationFlags,
355+
LPDWORD lpThreadId);
356+
357+
HANDLE CreateRemoteThread(
358+
HANDLE hProcess,
359+
LPSECURITY_ATTRIBUTES lpThreadAttributes,
360+
SIZE_T dwStackSize,
361+
LPTHREAD_START_ROUTINE lpStartAddress,
362+
LPVOID lpParameter,
363+
DWORD dwCreationFlags,
364+
LPDWORD lpThreadId
365+
);
366+
367+
typedef ULONG_PTR DWORD_PTR;
368+
369+
typedef struct _PROC_THREAD_ATTRIBUTE_ENTRY
370+
{
371+
DWORD_PTR Attribute;
372+
SIZE_T cbSize;
373+
PVOID lpValue;
374+
} PROC_THREAD_ATTRIBUTE_ENTRY, *LPPROC_THREAD_ATTRIBUTE_ENTRY;
375+
376+
// This structure contains a list of attributes that have been added using UpdateProcThreadAttribute
377+
typedef struct _PROC_THREAD_ATTRIBUTE_LIST
378+
{
379+
DWORD dwFlags;
380+
ULONG Size;
381+
ULONG Count;
382+
ULONG Reserved;
383+
PULONG Unknown;
384+
PROC_THREAD_ATTRIBUTE_ENTRY Entries[1];
385+
} PROC_THREAD_ATTRIBUTE_LIST, *LPPROC_THREAD_ATTRIBUTE_LIST;
386+
387+
HANDLE CreateRemoteThreadEx(
388+
HANDLE hProcess,
389+
LPSECURITY_ATTRIBUTES lpThreadAttributes,
390+
SIZE_T dwStackSize,
391+
LPTHREAD_START_ROUTINE lpStartAddress,
392+
LPVOID lpParameter,
393+
DWORD dwCreationFlags,
394+
LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
395+
LPDWORD lpThreadId
396+
);
397+
398+
struct S
399+
{
400+
int x;
401+
};
402+
403+
DWORD ThreadProc1(LPVOID lpParameter)
404+
{
405+
S *s = (S *)lpParameter;
406+
sink(s->x); // $ ir
407+
return 0;
408+
}
409+
410+
DWORD ThreadProc2(LPVOID lpParameter)
411+
{
412+
S *s = (S *)lpParameter;
413+
sink(s->x); // $ ir
414+
return 0;
415+
}
416+
417+
DWORD ThreadProc3(LPVOID lpParameter)
418+
{
419+
S *s = (S *)lpParameter;
420+
sink(s->x); // $ ir
421+
return 0;
422+
}
423+
424+
int source();
425+
426+
void test_create_thread()
427+
{
428+
SECURITY_ATTRIBUTES sa;
429+
430+
S s;
431+
s.x = source();
432+
433+
{
434+
DWORD threadId;
435+
HANDLE threadHandle = CreateThread(
436+
&sa,
437+
0,
438+
ThreadProc1,
439+
&s,
440+
0,
441+
&threadId);
442+
}
443+
444+
{
445+
DWORD threadId;
446+
HANDLE threadHandle = CreateRemoteThread(
447+
nullptr,
448+
&sa,
449+
0,
450+
ThreadProc2,
451+
&s,
452+
0,
453+
&threadId);
454+
}
455+
456+
{
457+
DWORD threadId;
458+
PROC_THREAD_ATTRIBUTE_LIST attrList;
459+
HANDLE threadHandle = CreateRemoteThreadEx(
460+
nullptr,
461+
&sa,
462+
0,
463+
ThreadProc3,
464+
&s,
465+
0,
466+
&attrList,
467+
&threadId);
468+
}
469+
}

0 commit comments

Comments
 (0)