Intercepting An Application During Runtime

Apr 4, 2013 at 1:53 PM
As a simple demo, I have an application that takes a user name and password. It does a check and if the details are correct, it takes you the next form. Simple.
I want to intercept this traffic, so when I click the button to login, I can view and adjust the details of the username and password.


Currently, I have CInject injected and it is logging application. How would I then intercept the data?

Thanks in advance.
Coordinator
Apr 4, 2013 at 2:41 PM
Edited Apr 4, 2013 at 2:47 PM
Solution 1:
This is possible only if your target application has a function that takes the username and password as arguments from the UI and then does some processing in it.

Steps
  1. Create your own interceptor
  2. In the method OnInvoke(CInjection injection), check for the argument index/type and take action accordingly. The arguments to the target method are available in the CInjection.Arguments property
  3. Inject using CInject and Run it on the target application
  4. Execute the new injected application
Solution 2:
This is possible if your target application does not have a function taking username and password as arguments

Steps (slightly complex)
  1. Create your own interceptor
  2. In the method OnInvoke(CInjection injection), instead of checking the values of arguments, use reflection to find public/private variables of the instantiated class (not the interceptor).
  3. Once you find the public/private variables, then search for the type TextBox that refers to username / password
  4. Inject using CInject and Run it on the target application
  5. Execute the new injected application
Code for reflection:
PropertyInfo[] properties = typeof(this).GetProperties(BindingFlags.Public | BindingFlags.Instance);

    foreach (PropertyInfo p in properties)
    {     

        // If not writable then cannot null it; if not readable then cannot check it's value
        if (!p.CanWrite || !p.CanRead) { continue; }

        MethodInfo mget = p.GetGetMethod(false);
        MethodInfo mset = p.GetSetMethod(false);

        // Get and set methods have to be public
        if (mget == null) { continue; }
        if (mset == null) { continue; }

        var pValue = p.GetValue(item, null);
    }
or
var properties = (from prop
                              in this.GetType()
                                .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                          where                             
                            prop.CanWrite && 
                            prop.CanRead
                          select prop).ToList();
Apr 15, 2013 at 10:28 AM
Hi,

Thanks for your reply.

I have followed your tutorial (http://www.ganshani.com/2011/09/28/cinject-quick-guide/) and have created a plugin like the one you demostrated.

I have injected into my application and loaded in the injector.

I've copied the files where they need to be and a log is kept. However, I can't see any evidence of the injector in the logs.
using System.Text;
using System.Threading.Tasks;
using CInject.Injections.Interfaces;

namespace ClassLibrary1
{
    public class Class1 : ICInject
    {
        public void OnInvoke(CInject.Injections.Library.CInjection injection)
        {
            try
            {
                Console.WriteLine("Hey, does this work?");
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception);
            }
        }
        public void OnComplete()
        {
        }
    }
}
Is there something I'm missing in my code or in my actions?
Thanks.
Coordinator
Apr 15, 2013 at 11:20 AM

Are you referring to a plugin or injector? The code you posted looks like an injector.

Can you post a part of application code? Have you copied all the assemblies in a folder and tried injecting?

Apr 15, 2013 at 12:31 PM
Edited Apr 15, 2013 at 12:31 PM
An Injector. As you mentionned in Soultion 1.

To date, I've been copying the target application into the same folder as CInject. That's been working fine.

As for my target application, the logic is very simple.
SImple, enter a username and password. If it's correct, proceed to a second form (it has fields but they are inactive for the moment.) . If it's wrong display a message.

I would like to use CInject, to bypass the login authenication by ammending the data they've entered:
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (uName.Text.Equals("Admin") && pWord.Text.Equals("admin"))
            {
                Form2 form = new Form2();
                form.Show();
            }
            else
            {
                MessageBox.Show("Invalid user details please try again");
            }
        }
    }
}
Here is the link to my injector and application:
http://www.mediafire.com/?1e8icz6462lfbw5
(Login details are of course: 'Admin' and pass 'admin')

Thanks for your help :)
Coordinator
Apr 15, 2013 at 12:48 PM
I injected Class1 into your code and it worked without any problems.
May be because you have written Console.WriteLine, you are unable to see the change. See the log file created to check that injection

2013-04-15 20:42:53,561 [1] INFO xxxx Invoked Program.Main, xxxx
2013-04-15 20:42:55,799 [1] INFO xxxx Invoked Form1.InitializeComponent, xxxx
2013-04-15 20:42:57,383 [1] INFO xxxx Completed Form1.InitializeComponent, xxxx
2013-04-15 20:42:57,384 [1] INFO xxxx InitializeComponent executed in 1585.2876 mSec
2013-04-15 20:43:03,133 [1] INFO xxxx Invoked Form1.button1_Click, xxxx
2013-04-15 20:43:03,133 [1] DEBUG xxxx >> Paramerters: 2
2013-04-15 20:43:05,462 [1] DEBUG xxxx [sender]: System.Windows.Forms.Button, Text: Login
2013-04-15 20:43:05,640 [1] DEBUG xxxx [e]: System.Windows.Forms.MouseEventArgs
2013-04-15 20:43:09,513 [1] INFO xxxx Completed Form1.button1_Click, xxxx
2013-04-15 20:43:09,514 [1] INFO xxxx button1_Click executed in 6380.1593 mSec
2013-04-15 20:43:11,481 [1] INFO xxxx Invoked Form1.Dispose, xxxx
2013-04-15 20:43:11,481 [1] DEBUG xxxx >> Paramerters: 1
2013-04-15 20:43:12,158 [1] DEBUG xxxx [disposing]: ?<?xml version="1.0" encoding="utf-8"?><boolean>true</boolean>
2013-04-15 20:43:12,345 [1] INFO xxxx Completed Form1.Dispose, xxxx
2013-04-15 20:43:12,345 [1] INFO xxxx Dispose executed in 863.5785 mSec
2013-04-15 20:43:12,417 [1] INFO xxxx Completed Program.Main, xxxx
2013-04-15 20:43:12,417 [1] INFO xxxx Main executed in 21105.1946 mSec
Apr 16, 2013 at 10:05 AM
Edited Apr 16, 2013 at 11:06 AM
Hi,
Ah, my mistake.
Yes it's working now thanks :)

My issue was with the Console.WriteLine. I was expecting to see the message: 'hey does this work' in the log.
Out of interest, where is data from the 'ConsoleWriteLine' printed too? I can't see the data in my logs, or in CInject. Where should I be looking for this information?
Coordinator
Apr 16, 2013 at 11:13 AM

To test you can use log4net first. That would definitely print it in the log file.

The best way then would be to find out type of application and then use appropriate API. If its a Windows Application, MessageBox should work.

Apr 16, 2013 at 11:53 AM
Edited Apr 16, 2013 at 11:54 AM
Thanks for your prompt support. I'm sure I'l be able to get the hang of this.

I'm using the MessageBox and that works fine for displaying messages. I've used the code avaiable from here: https://codeinject.codeplex.com/documentation
namely, the for loop to ileterate through the data and print it out. However, I've noticed that my application crashes when calls are made to Injection.Argument. Namely at:
injection.Arguments[i].ToString();
and
injection.Arguments.Length
My Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CInject.Injections.Interfaces;
using CInject.Injections.Library;

namespace ClassLibrary1
{
    public class Class1 : ICInject
    {
        public void OnInvoke(CInjection injection)
        {
            try
            {               
                MessageBox.Show("" + injection.Arguments[1].ToString());
            }
            catch
            {
                throw;
            }
        }
        public void OnComplete()
        {         
        }
    }
}
(Note: I've tried using a range of indexes (0,1 etc) and it didn't work when I used the code provided in the above documentation)

The log files show it launched but nothing else from it:
2013-04-16 12:48:24,067 [1] INFO     HackProject     Invoked Program.Main, HackProject
2013-04-16 12:49:02,726 [1] INFO     HackProject     Invoked Program.Main, HackProject
2013-04-16 12:52:38,682 [1] INFO     HackProject     Invoked Program.Main, HackProject
Coordinator
Apr 16, 2013 at 11:57 AM
Is the value of Arguments null?
From: MatthewSeaward
Sent: ‎Tuesday‎, ‎16‎ ‎April‎ ‎2013 ‎7‎:‎53‎ ‎PM
To: [email removed]

From: MatthewSeaward

Thanks for your prompt support. I'm sure I'l be able to get the hang of this.

I'm using the MessageBox and that works fine for displaying messages. I've used the code avaiable from here: https://codeinject.codeplex.com/documentation
namely, the for loop to ileterate through the data and print it out. However, I've noticed that my application crashes when calls are made to Injection.Argument. Namely at:
injection.Arguments[i].ToString();
and
injection.Arguments.Length
My Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CInject.Injections.Interfaces;
using CInject.Injections.Library;

namespace ClassLibrary1
{
    public class Class1 : ICInject
    {
        public void OnInvoke(CInjection injection)
        {
            try
            {               
                MessageBox.Show("" + injection.Arguments[1].ToString());
            }
            catch
            {
                throw;
            }
        }
        public void OnComplete()
        {         
        }
    }
}
The log files show it launched but nothing else from it:
2013-04-16 12:48:24,067 [1] INFO     HackProject     Invoked Program.Main, HackProject
2013-04-16 12:49:02,726 [1] INFO     HackProject     Invoked Program.Main, HackProject
2013-04-16 12:52:38,682 [1] INFO     HackProject     Invoked Program.Main, HackProject
Apr 16, 2013 at 12:35 PM
I'm not sure to be honest. I've only copied your code. :/


Apr 17, 2013 at 2:11 PM
Edited Apr 17, 2013 at 2:17 PM
Hi,

I've realised my error and have finally cracked it.

Yes, the data was empty, but causing it to crash seemed to reply upon the try/catch. After adjusting the error, my application now works as expected.

The data is intercepted and can be modified during the application runtime. thanks for your help.

One small, quick question.
I've been able to modify the values that are sent to the method. However, how will I adjust the values returned?
        public Boolean correctLoginDetails(String uName, String pWord)
        {
            if (uName.Equals(username) && pWord.Equals(password))
                return true;
            else
                return false;
        }
At the moment, I can change the 'uName' and 'pWord'
How can I change the Boolean that is returned? (for example, changing it to 'true' whether or not the details are correct.

I've checked the methods available in the injection but haven't found anything which seems to do this...
Coordinator
Apr 17, 2013 at 2:33 PM

To change return value at the moment is not possible as it is just intercepting input values.

I would be glad if you could post a review on usage and ease of implementation. Thanks
Apr 18, 2013 at 10:03 AM
^ ah okay.

Yes I will gladly do that, once I've finished my developing.

I am just trying to change the variable and I have tried two approaches:
injection.Arguments.SetValue("Blahhh", 1);
This runs fine but the values haven't been changed.
injection.Method.GetParameters().SetValue("Blahhh", 0);
This causes a run time error around the SetValue area.

Am I doing this correctly?
Coordinator
Apr 25, 2013 at 2:11 PM