API Endpoint Discovery from IIS Server¶
Category: API Discovery Tags: API endpoints, IIS, PowerShell reflection, .NET assembly analysis, web API discovery
This guide explains how to discover all API endpoints from an IIS server's API application pool using PowerShell reflection without external tools.
API Application Path Discovery¶
What it does:
- Get-IISApplication - Retrieves all IIS applications configured on the server
- Where-Object {$_.Path -like "*api*"} - Filters applications whose path contains "api"
- Select Path, PhysicalPath - Shows both the virtual path (like "/api") and physical disk path (like "C:\inetpub\wwwroot\api")
Purpose: Locates where your API application files are stored on disk.
Assembly File Enumeration¶
What it does:
- Get-ChildItem *.dll - Lists all .dll files in the current directory (bin folder)
- Select Name - Shows only the filename of each DLL
Purpose: Identifies which assemblies contain your API code. Look for files named like <YourProject>.Api.dll or <CompanyName>.WebApi.dll.
Assembly Loading Process¶
What it does:
- [System.Reflection.Assembly]::LoadFile() - .NET reflection method that loads a compiled assembly into memory
- <full_path_to_api_dll> - Replace with complete path like "C:\inetpub\wwwroot\api\bin\YourApi.dll"
- $assembly - Stores the loaded assembly object for further inspection
Purpose: Loads your API's compiled code so we can examine its structure programmatically.
Controller Class Discovery¶
$assembly.GetTypes() | Where-Object {$_.Name -like "*Controller*"} | ForEach-Object {
Write-Host $_.Name
$_.GetMethods() | Where-Object {$_.IsPublic} | Select-Object Name
}
What it does:
- $assembly.GetTypes() - Gets all classes/types defined in the assembly
- Where-Object {$_.Name -like "*Controller*"} - Filters to classes with "Controller" in the name
- ForEach-Object - Loops through each controller class
- Write-Host $_.Name - Prints the controller class name
- $_.GetMethods() - Gets all methods (functions) in that controller
- Where-Object {$_.IsPublic} - Filters to only public methods (API endpoints are public)
- Select-Object Name - Shows method names
Purpose: Discovers all API controller classes and their public methods, which represent your API endpoints.
Endpoint Route Extraction¶
$controllers = $assembly.GetTypes() | Where-Object {$_.BaseType.Name -eq "ApiController"}
$controllers | ForEach-Object {
$controller = $_
$controller.GetMethods() | Where-Object {$_.IsPublic -and $_.DeclaringType -eq $controller} |
ForEach-Object { "$($controller.Name): $($_.Name)" }
}
What it does:
- Where-Object {$_.BaseType.Name -eq "ApiController"} - Finds classes that inherit from ApiController (Web API 2) or ControllerBase (Web API Core)
- $_.DeclaringType -eq $controller - Ensures we only get methods defined in this controller (not inherited ones)
- "$($controller.Name): $($_.Name)" - Formats output as "ControllerName: MethodName"
Purpose: Creates a clean list showing which controller contains which endpoint methods.
Route Attribute Analysis¶
$controllers | ForEach-Object {
$controller = $_
$controller.GetMethods() | ForEach-Object {
$method = $_
$attributes = $method.GetCustomAttributes($true)
$routeAttr = $attributes | Where-Object {$_.GetType().Name -like "*Route*"}
if($routeAttr) {
"$($controller.Name.Replace('Controller','')): $($method.Name) -> $($routeAttr.Template)"
}
}
}
What it does:
- $method.GetCustomAttributes($true) - Gets all attributes applied to the method (like [HttpGet], [Route])
- Where-Object {$_.GetType().Name -like "*Route*"} - Finds routing attributes
- $routeAttr.Template - Extracts the actual route template (like "api/users/{id}")
- Replace('Controller','') - Removes "Controller" suffix for cleaner output
Purpose: Shows the actual HTTP routes/URLs for each endpoint, not just method names.
Expected Discovery Results¶
After running these commands, you'll see output like:
UsersController: GetUsers
UsersController: GetUser
UsersController: CreateUser
UsersController: UpdateUser
UsersController: DeleteUser
ProductsController: GetProducts
ProductsController: GetProduct
Assembly Naming Conventions¶
Look for DLLs named:
- <ProjectName>.Api.dll
- <ProjectName>.WebApi.dll
- <CompanyName>.Services.dll
- Api.dll
- WebApi.dll
Common Issues and Solutions¶
If no controllers found:
- Try Where-Object {$_.BaseType.Name -eq "ControllerBase"} for .NET Core APIs
- Check if DLL is the right one by examining $assembly.GetTypes() | Select Name
If assembly won't load: - Ensure you have read permissions to the bin directory - Try copying DLL to a temp folder first - Check if DLL has dependencies that aren't loaded