+ All Categories
Home > Documents > General Purpose Binary Rewriting

General Purpose Binary Rewriting

Date post: 03-Apr-2022
Category:
Upload: others
View: 5 times
Download: 0 times
Share this document with a friend
59
General Purpose Binary Rewriting Mihai Christodorescu [email protected] WiSA http://www.cs.wisc.edu/wisa University of Wisconsin, Madison
Transcript
Page 1: General Purpose Binary Rewriting

General PurposeBinary Rewriting

Mihai [email protected]

WiSA http://www.cs.wisc.edu/wisaUniversity of Wisconsin, Madison

Page 2: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 2 of 59

Overview1. Introduction to binary rewriting

2. Benefits and applications of binary rewriting

3. Existing tools

4. Architecture for rewriting

5. Implementation status

6. Future work

7. Protection against malicious rewriting

Page 3: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 3 of 59

Binary Rewriting• Transform a binary executable

based on input rules– Add / remove / edit code

P.exe BinaryRewriter

Q.exe

R.exe

Ruleset 1

Ruleset 2

Page 4: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 4 of 59

Binary Rewriting• No source code is needed

– Commercial component software– Independent of programming

language• Treats multi-language systems

consistently

• Complete access to the binary– Not affected by optimizations

Page 5: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 5 of 59

Binary Rewriting• Works regardless of program

design– Similar to AOP– Apply transforms across the

program

• Extremely powerful

Page 6: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 6 of 59

Overview1. Introduction to binary rewriting

2. Benefits and applications of binary rewriting

3. Existing tools

4. Architecture for rewriting

5. Implementation status

6. Future work

7. Protection against malicious rewriting

Page 7: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 7 of 59

Binary Rewriting Applications• Historically:

– Program optimization• Based on profiling data

– Performance instrumentation

– Virus / worm infection• Using obfuscation

Page 8: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 8 of 59

Program Obfuscation• Used by viruses

– Add code to make detection harder

– No change in program behavior

• Competition:– Antivirus tools try to deobfuscate– Virus writers try to obfuscate

Page 9: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 9 of 59

Program Obfuscation• Semantic NOP Insertion

– Add code fragment that does not modify program behavior

• Variable / Register Renaming– Change the name of program variables

• Instruction Reordering– Change the order of instructions without

modifying program behavior

• Encode Program

Page 10: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 10 of 59

Loop:pop ecx

jecxz SFModMark

mov esi, ecx

mov eax, 0d601hpop edxpop ecx

call edi

jmp Loop

Morphed Virus Code(based on Chernobyl CIH 1.4):

Obfuscation Example for x86

Loop:pop ecxjecxz SFModMarkmov esi, ecxmov eax, 0d601hpop edxpop ecxcall edijmp Loop

Virus Code(from Chernobyl CIH 1.4):

nop

xor ebx, ebxbeqz N1

N1:nop

nop

xor ebx, ebxbeqz N2

N2:

Page 11: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 11 of 59

Loop:pop ecx

Morphed Virus Code(based on Chernobyl CIH 1.4):

Obfuscation Example for x86

Loop:pop ecxjecxz SFModMarkmov esi, ecxmov eax, 0d601hpop edxpop ecxcall edijmp Loop

Virus Code(from Chernobyl CIH 1.4):

xor ebx, ebxbeqz N2

N2: jmp Loop

pop ecxnopcall edi

beqz N1N1: mov esi, ecx

nopmov eax, 0d601hpop edx

nopjecxz SFModMarkxor ebx, ebx

Page 12: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 12 of 59

Loop:pop ecxjmp L1xor ebx, ebxbeqz N2

N2: jmp Loopnopjecxz SFModMarkxor ebx, ebxjmp L2pop ecxnopcall edijmp L4beqz N1

N1: mov esi, ecxnopmov eax, 0d601hpop edxjmp L3

Morphed Virus Code(based on Chernobyl CIH 1.4):

Obfuscation Example for x86

Loop:pop ecxjecxz SFModMarkmov esi, ecxmov eax, 0d601hpop edxpop ecxcall edijmp Loop

Virus Code(from Chernobyl CIH 1.4):

L2:

L3:

L4:

L1:

Page 13: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 13 of 59

Loop:pop ecxjmp L1

L4: xor ebx, ebxbeqz N2

N2: jmp LoopL1: nop

jecxz SFModMarkxor ebx, ebxjmp L2

L3: pop ecxnopcall edijmp L4

L2: beqz N1N1: mov esi, ecx

nopmov eax, 0d601hpop edxjmp L3

Morphed Virus Code(based on Chernobyl CIH 1.4):

Obfuscation Example for x86

Loop:pop ecxjecxz SFModMarkmov esi, ecxmov eax, 0d601hpop edxpop ecxcall edijmp Loop

Virus Code(from Chernobyl CIH 1.4):

Page 14: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 14 of 59

Loop:pop eaxjmp L1

L4: xor ebx, ebxbeqz N2

N2: jmp LoopL1: nop

jecxz SFModMarkxor ebx, ebxjmp L2

L3: pop eaxnopcall edijmp L4

L2: beqz N1N1: mov esi, eax

nopmov ecx, 0d601hpop edxjmp L3

Morphed Virus Code(based on Chernobyl CIH 1.4):

Obfuscation Example for x86

Loop:pop ecxjecxz SFModMarkmov esi, ecxmov eax, 0d601hpop edxpop ecxcall edijmp Loop

Virus Code(from Chernobyl CIH 1.4):

Page 15: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 15 of 59

Loop:pop eaxjmp L1

L4: xor ebx, ebxbeqz N2

N2: jmp LoopL1: nop

jecxz SFModMarkxor ebx, ebxjmp L2

L3: pop eaxnopcall edijmp L4

L2: beqz N1N1: mov esi, eax

nopmov ecx, 0d601hpop edxjmp L3

Morphed Virus Code(based on Chernobyl CIH 1.4):

Obfuscation Example for x86

Loop:pop ecxjecxz SFModMarkmov esi, ecxmov eax, 0d601hpop edxpop ecxcall edijmp Loop

Virus Code(from Chernobyl CIH 1.4):

Page 16: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 16 of 59

Obfuscation Example for VB

On Error Resume Next...Set outlookObj = CreateObject("Outlook.Application")...For Each addressObj In addressBookObj

...newMsgObj.Send...

Next...'Vbswg 1.50b

Worm Code(based on AnnaKournikova worm):

Page 17: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 17 of 59

Obfuscation Example for VB

Execute “On Error Resume Next\n...\nSet outlookObj= CreateObject("Outlook.Application")\n...\nFor Each addressObj In addressBookObj\n...\nnewMsgObj.Send\n...\nNext\n...\n'Vbswg1.50b”

Worm Code(based on AnnaKournikova worm):

Page 18: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 18 of 59

Obfuscation Example for VB

Execute F( “X)udQ0Vpgjn... udiy3^Q70d2” )

Function F(S)For I = 1 To Len(S) Step 2

X= Mid(S, I, 1)...If Asc(X) = 15 Then

...End If...

NextEnd Function

Worm Code(based on AnnaKournikova worm):

Page 19: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 19 of 59

Program Obfuscation• Obfuscation is a technique used by

virus writers

=> Virus detection tools have to handle obfuscations

• Then, to test our virus detection tool, we need to rewrite infected binaries to add obfuscations

Page 20: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 20 of 59

Obfuscating…

Chernobyl-1.4

f0sf0r0

Hare

z0mbie-6.b

Commercial antivirus tools vs. morphed versions of known viruses

Not detected

Not detected

Not detected

Not detected

Not detected

Not detected

Not detected

Not detected

Not detected

Not detected

Not detected

Not detected

Page 21: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 21 of 59

Program Obfuscation• The obfuscation war is not lost

– We can effectively deobfuscatemany idioms

– More later

• Benefit of obfuscation:– IP protection (harder to reverse

engineer)

Page 22: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 22 of 59

Bounds Checking• C, C++ do not perform bounds

checking on array accesses– Possible buffer overflow due to

programming errors

• Patch all string buffer and array accesses to check for length

=> No more buffer overflows

Page 23: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 23 of 59

Sandboxing• Restrict untrusted program’s

access to OS interface:– Contain disk access & memory usage– Allow / deny network connections– No OS modification

Host

Network .exe

Page 24: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 24 of 59

Security Policy Enforcement• Similar to Engler’s metacompilation

work

• Enforce rules not supported by the standard OS security mechanisms:

– Sanitize untrusted input– Do not release sensitive data to users– Check custom permissions before doing

operation X

Page 25: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 25 of 59

Security Policy Enforcement• Powerful to check at runtime:

– Programming errors that can lead to security flaws

– Security violations

• Technique:– Add code that at runtime

enforces desired rules

Page 26: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 26 of 59

Program Monitoring• Monitor a running program to

prevent malicious modification

• A monitor process will:– Trace the events produced by a

running program– Make sure the events match what

is expected

Page 27: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 27 of 59

Program Monitoring

• Monitoring can be remote or local

• Flexible policy rules

UntrustedProcess

MonitorProcess

Rulesof

expectedbehavior

Page 28: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 28 of 59

Program Monitoring• Problem:Certain event sequences are ambiguous

• Solution:Modify program to eliminate ambiguity

(as much as possible)– Insert code to send special events– See Jon Giffin’s work on IDS

Page 29: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 29 of 59

Overview1. Introduction to binary rewriting

2. Benefits and applications of binary rewriting

3. Existing tools

4. Architecture for rewriting

5. Implementation status

6. Future work

7. Protection against malicious rewriting

Page 30: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 30 of 59

Existing Binary Rewriters

• Limited in functionality or scope

• Some still in prototype mode

Page 31: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 31 of 59

Existing Binary Rewriters• EEL (Executable Editing Library)

(U. Wisconsin)

– Works only on SPARC binaries

• Etch Binary Rewriter(U. Washington)

– Works only on x86 Windows– Not available as a separate library

Page 32: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 32 of 59

Existing Binary Rewriters• Byte Code Engineering Library

(Open source, Apache Foundation)

– Java specific

• OM / ATOM(DEC WRL/Compaq WRL/HP?)

– proprietary

Page 33: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 33 of 59

Existing Binary Rewriters• DynInst

(U. Wisconsin, U. Maryland)

– Geared towards instrumentingrunning programsCan handle multiple types of binaries

Page 34: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 34 of 59

The Problem• WiSA project relies on several

tools:– EEL, IDA Pro, CodeSurfer + custom

code

• Incomplete solution:– Platform specific (not cross platform)– Missing features, yet not easily

extensible

Page 35: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 35 of 59

Overview1. Introduction to binary rewriting

2. Benefits and applications of binary rewriting

3. Existing tools

4. Architecture for rewriting

5. Implementation status

6. Future work

7. Protection against malicious rewriting

Page 36: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 36 of 59

Goal• General purpose binary rewriter

– Cross platform• Windows, Linux, Solaris, ...

– Multiple architectures• IA-32 (x86), IA-64, SPARC, ...

– Extensible– Flexible– Useful

Page 37: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 37 of 59

Binary Rewriter Architecture

CFG transformer

program

front-end

CFG + other info

back-end

new CFG

new program

transformation parameters

SPARC FEx86 FE VB FE Java FE

x86 binary SPARC bin VB app Java class

SPARC BEx86 BE Java BEVB BE

x86 binary SPARC bin VB app Java class

Page 38: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 38 of 59

Seems easy enough...• Different architectures• Different execution

environments• Different languages

=> Bringing all of them into one data structure is a challenge!

Page 39: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 39 of 59

Seems easy…• Each architecture has features

non-existent elsewhere– SPARC has register windows– IA-32 (x86) has a hardware stack– ...

• Did we mention it has to be flexible, customizable, and extensible?

Page 40: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 40 of 59

Binary Rewriter Design• Binary rewriter interface ─

multiple levels of abstraction:

– Hide architecture-specific differences when needed

– Provide low level details when necessary

Page 41: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 41 of 59

Binary Rewriter• A project worth undertaking:

– The benefits are extraordinary

• The infrastructure can be reused...

Page 42: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 42 of 59

Binary Rewriter Architecture

CFG transformer

program

front-end

CFG + other info

back-end

new CFG

new program

transformation parameters

SPARC FEx86 FE VB FE Java FE

x86 binary SPARC bin VB app Java class

SPARC BEx86 BE Java BEVB BE

x86 binary SPARC bin VB app Java class

Static analyzer 1

Static analyzer 2

program info

...

Page 43: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 43 of 59

Overview1. Introduction to binary rewriting

2. Benefits and applications of binary rewriting

3. Existing tools

4. Architecture for rewriting

5. Implementation status

6. Future work

7. Protection against malicious rewriting

Page 44: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 44 of 59

Status• Early stage

– Gathering requirements• From WiSA subprojects• From external sources

– Assessing tools used by WiSA• Some tools to be integrated in the

new infrastructure• Some tools have good interfaces

Page 45: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 45 of 59

Status• Current tools

– IDA Pro• Supports multiple architectures• Can act as a front-end only• Front-end for x86 – good progress

– CodeSurfer• Multiple, complex static analyses

– EEL• Good interface• Support for SPARC rewriting

Page 46: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 46 of 59

Status• CFG transformer

– Some transformations have ad-hoc implementations

– Specification and design in progress

=> The work done up to now can be integrated and reused

Page 47: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 47 of 59

Overview1. Introduction to binary rewriting

2. Benefits and applications of binary rewriting

3. Existing tools

4. Architecture for rewriting

5. Implementation status

6. Future work

7. Protection against malicious rewriting

Page 48: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 48 of 59

Steps Forward1. Architecture and design

– Documented & reviewed2. Define interfaces

– Based on existing tools– Focus on integration with existing tools

3. Prototype implemented– Support several key architectures– Test and get feedback on interface

design issues

Page 49: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 49 of 59

More Steps Forward4. Review design

– Based on internal feedback5. Implementation

– Complete front-ends and back-ends– Several transformations ported to the

new infrastructure– Static analyses ported to the new

infrastructure6. Release

Page 50: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 50 of 59

Future Work• Support many static analyses

– Incremental precision gains– Enhance infrastructure info

• Add transformations of increasing complexity

• Add more architectures / languages

Page 51: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 51 of 59

Overview1. Introduction to binary rewriting

2. Benefits and applications of binary rewriting

3. Existing tools

4. Architecture for rewriting

5. Implementation status

6. Future work

7. Protection against malicious rewriting

Page 52: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 52 of 59

Seeing Through the Obfuscations

Malicious CodeBlueprint

Programto analyze

PatternLibrary

Annotator

AnnotatedProgram Model Checker

Yes/No

IDA Pro + CodeSurfer +

custom analysis code

Custom-built

Smart Virus Scanner

Page 53: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 53 of 59

Detection Example

push eaxsidt [esp-02h]pop ebxadd ebx, HookNo * 08h + 04hclimov ebp, [ebx]mov bp, [ebx-04h]lea esi, MyHook - @1[ecx]push esimov [ebx-04h], sishr esi, 16mov [ebx+02h], sipop esi

Virus Code:

Virus Automaton:

mov X, Y

mov X1, Z

lea A, B

Irrelevant instruction

Irrelevant instruction

Irrelevant instruction

VirusFound!

(from Chernobyl CIH 1.4 virus)

Page 54: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 54 of 59

mov ebp, [ebx]nopmov bp, [ebx-04h]test ebxbeqz next

next: lea esi, MyHook - @1[ecx]

Program to be checked:

Detection Example

mov ebp, [ebx]

Irrelevant

lea esi, MyHook - @1[ecx]

mov bp, [ebx-04h]

Irrelevant

Irrelevant

Annotated program:

Page 55: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 55 of 59

mov X, Y

mov X1, Z

lea A, B

Irrelevant

Irrelevant

Irrelevant

Detection Example

Virus Automaton:mov ebp, [ebx]

Irrelevant

lea esi, MyHook - @1[ecx]

mov bp, [ebx-04h]

Irrelevant

Irrelevant

Program model (annotated program):

X = ebpY = [ebx]Z = [ebx – 04h]A = esiB = MyHook - @1[ecx]

Page 56: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 56 of 59

Smart Virus Scanner• What are irrelevant instructions?

– NOPs

– Control flow instructions that do not change the control flow

• e.g.: jumps/branches to the next instructions

– Instructions that modify dead registers

– Sequences of instructions that do not modify architectural state

• e.g.:add ebx, 1sub ebx, 1

Page 57: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 57 of 59

Uninterpreted Symbols• What happens when the registers are

changed?

mov ebp, [ebx]nopmov bp, [ebx-04h]test ebxbeqz next

next: lea esi, MyHook - @1[ecx]

mov eax, [ecx]nopmov ax, [ecx-04h]test edxbeqz next

next: lea ebi, MyHook - @1[ebx]

Program 1: Program 2:

Virus Spec:mov ebp, [ebx] => No match with Program 2

Virus Spec with Uninterpreted Symbols:mov X, Y => Matches both Programs 1 and 2

Page 58: General Purpose Binary Rewriting

January 25, 2003Mihai Christodorescu [email protected] Project http://www.cs.wisc.edu/wisa Page 58 of 59

Program Obfuscations• Semantic NOPs• Instruction Reordering• Variable Renaming

– Handled through static analysis

• Encoded Program Fragment– Partial evaluation

Page 59: General Purpose Binary Rewriting

General PurposeBinary Rewriting

Mihai [email protected]

WiSA http://www.cs.wisc.edu/wisaUniversity of Wisconsin, Madison


Recommended