how to intentionally corrupt a file in java
Note: Please do not judge this question. To those who think that I am doing this to «cheat»; you are mistaken, as I am no longer in school anyway. In addition, if I was, myself actually trying to cheat, I would simply use services that have already been created for this, instead of recreating the program. I took on this project because I thought it might be fun, nothing else. Before you down-vote, please consider the value of the question it’s self, and not the speculative uses of it, as the purpose of SO is not to judge, but simply give the public information. I am developing a program in java that is supposed intentionally corrupt a file (specifically a .doc, txt, or pdf, but others would be good as well) I initially tried this:
public void corruptFile (String pathInName, String pathOutName) < curroptMethod method = new curroptMethod(); ArrayListcorruptHash = corrupt(getBytes(pathInName)); writeBytes(corruptHash, pathOutName); new MimetypesFileTypeMap().getContentType(new File(pathInName)); // "/home/ephraim/Desktop/testfile" > public ArrayList getBytes(String filePath) < ArrayListfileBytes = new ArrayList(); try < FileInputStream myInputStream = new FileInputStream(new File(filePath)); do < int currentByte = myInputStream.read(); if(currentByte == -1) < System.out.println("broke loop"); break; >fileBytes.add(currentByte); > while (true); > catch (FileNotFoundException e) < // TODO Auto-generated catch block e.printStackTrace(); >catch (IOException e) < // TODO Auto-generated catch block e.printStackTrace(); >System.out.println(fileBytes); return fileBytes; > public void writeBytes(ArrayList hash, String pathName) < try < OutputStream myOutputStream = new FileOutputStream(new File(pathName)); for (int currentHash : hash) < myOutputStream.write(currentHash); >> catch (FileNotFoundException e) < // TODO Auto-generated catch block e.printStackTrace(); >catch (IOException e) < // TODO Auto-generated catch block e.printStackTrace(); >//System.out.println(hash); > public ArrayList corrupt(ArrayList hash) < ArrayListcorruptHash = new ArrayList(); ArrayList keywordCodeArray = new ArrayList(); Integer keywordIndex = 0; String keyword = "corruptthisfile"; for (int i = 0; i < keyword.length(); i++) < keywordCodeArray.add(keyword.codePointAt(i)); >for (Integer currentByte : hash) < //Integer currentByteProduct = (keywordCodeArray.get(keywordIndex) + currentByte) / 2; Integer currentByteProduct = currentByte - keywordCodeArray.get(keywordIndex); if (currentByteProduct < 0) currentByteProduct += 255; corruptHash.add(currentByteProduct); if (keywordIndex == (keyword.length() - 1)) < keywordIndex = 0; >else keywordIndex++; > //System.out.println(corruptHash); return corruptHash; >
but the problem is that the file is still openable. When you open the file, all of the words are changed (and they may not make any sense, and they may not even be letters, but it can still be opened) so here is my actual question: Is there a way to make a file so corrupt that the computer doesn’t know how to open it at all (ie. when you open it, the computer will say something along the lines of «this file is not recognized, and cannot be opened»)?
How to identify whether file is corrupted in java [closed]
Answer your own question without «in java» first. How you identify whether a file is corrupted without Java?
The actual scenario is we have given a web application where user is allowed to upload documents, Now I want to restrict users to upload the corrupted files,means if user selects corrupted file to upload I have to give him a message that u hv selected corrupted file. So how I can identify a corrupted file using java
There is no such thing as «corrupted file» in general. There can be «two files differ» or «file is not in the expected format», the latter is not always easy to determine, especially for multimedia files.
1 Answer 1
You could get a MD5 or other checksum of the file and compare the values created on the client and server after the transfer though this would only tell you if the file was corrupted during transport and not that the original file is actually valid/correct for the intended use/type.
Files are just containers for bytes with some filesystem descriptors. How they are read and used by applications is specific to each and every file format. If you wanted to validate the contents of files prior to upload as actually valid for use by some application or another you will either need to implement (or find) code to evaluate every file you want to support in a different way according to the requirements for that type or perhaps try to read/load/use the file in some sand-boxed application instance beforehand (sand-boxed as invalid files may break things if really invalid or potentially malicious).
That’s a whole different ballgame. You will need to check for appropriate and correct file headers, content and more. What exactly depends entirely on what exact file types you are talking about. It will be a different solution for every type.
One method that could work is attempt to load and read the file in the background first. If there are any exceptions then the file «may» be corrupt. But again, you’ll have to handle every type differently. There isn’t a catch-all solution. What types are you trying to test?
Since I have given upload functionality to users, they can upload any file types, this we cant restrict. It would be very difficult if I have to write for every file types that is available in real world
You could perhaps write a few tests for the common file types being uploaded but as you say; it’s unrealistic to test every file type. You will have to accept the limitations or rework your design and restrict users to files that you do write tests for.
How to detect corrupted images (PNG, JPG) in Java
I need to detect if the image file is corrupted in Java. I’m working only with PNG, JPG images. Is this possible to do with Sanselan? Or can it be done with ImageIO? I’ve tried using ImageIO.read seems like it works. But I’m not sure if it can detect every kind of errors in images. I’d like to know what’s the best practice.
I would suggest that the only way to detect every kind of error in an image (where «error» is defined as any discrepancy which causes imperfect behaviour) is to go ahead and use the image. It’s entirely possible for an image to suffer a corruption which nonetheless results in a valid file, albeit one with «the wrong pixels». It may be useful to think very specifically about what it is you want to detect.
ImageIO can detect truncated PNG with an exception thrown, but for JPG that is truncated, I can’t get it to throw an exception.
4 Answers 4
Here is my solution that would handle checking for broken GIF, JPG and PNG. It checks for truncated JPEG using the JPEG EOF marker, GIF using an index out of bounds exception check and PNG using an EOFException
public static ImageAnalysisResult analyzeImage(final Path file) throws NoSuchAlgorithmException, IOException < final ImageAnalysisResult result = new ImageAnalysisResult(); final InputStream digestInputStream = Files.newInputStream(file); try < final ImageInputStream imageInputStream = ImageIO .createImageInputStream(digestInputStream); final IteratorimageReaders = ImageIO .getImageReaders(imageInputStream); if (!imageReaders.hasNext()) < result.setImage(false); return result; >final ImageReader imageReader = imageReaders.next(); imageReader.setInput(imageInputStream); final BufferedImage image = imageReader.read(0); if (image == null) < return result; >image.flush(); if (imageReader.getFormatName().equals("JPEG")) < imageInputStream.seek(imageInputStream.getStreamPosition() - 2); final byte[] lastTwoBytes = new byte[2]; imageInputStream.read(lastTwoBytes); if (lastTwoBytes[0] != (byte)0xff || lastTwoBytes[1] != (byte)0xd9) < result.setTruncated(true); >else < result.setTruncated(false); >> result.setImage(true); > catch (final IndexOutOfBoundsException e) < result.setTruncated(true); >catch (final IIOException e) < if (e.getCause() instanceof EOFException) < result.setTruncated(true); >> finally < digestInputStream.close(); >return result; > public class ImageAnalysisResult < boolean image; boolean truncated; public void setImage(boolean image) < this.image = image; >public void setTruncated(boolean truncated) < this.truncated = truncated; >> >
Why is this simple bit of code outputting a corrupted class file?
You have to invoke classReader.accept(classWriter) to reproduce the class file. With a ClassNode , it would be no different. You would have to invoke classReader.accept(classNode) , to populate it with the actual class information. Besides that, there is no sense in specifying ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES , as the COMPUTE_FRAMES option implies computing the max values already.
1 Answer 1
Your code lacks the step of actually copying the class features from the source to the destination:
try(FileInputStream in = new FileInputStream(new File("input.class"))
Passing the ClassReader to the ClassWriter ’s constructor does not copy the features, it rather enables optimizations, if your transformation keeps most of the original class files. Or, as the documentation of ClassWriter(ClassReader classReader, int flags) puts it:
- The constant pool and bootstrap methods from the original class are copied as is in the new class, which saves time. New constant pool entries and new bootstrap methods will be added at the end if necessary, but unused constant pool entries or bootstrap methods won’t be removed.
- Methods that are not transformed are copied as is in the new class, directly from the original class bytecode (i.e. without emitting visit events for all the method instructions), which saves a lot of time. Untransformed methods are detected by the fact that the ClassReader receives MethodVisitor objects that come from a ClassWriter (and not from any other ClassVisitor instance).
So, when you chain the ClassWriter directly to the ClassReader in the accept method, all method visitors will stem from the writer, hence, all of them are copied directly.
When you are going to change the class significantly or constructing a new class, you would use the constructor ClassWriter(int flags) instead.
Note that COMPUTE_FRAMES already implies COMPUTE_MAXS . In the example above, I specified neither, as the methods are copied anyway. When you are going to actually change or add code and need COMPUTE_FRAMES , it’s worth specifying SKIP_FRAMES to the reader, as there is no point in decoding the original frames when they get recalculated from scratch anyway.
So a typical transformation setup looks like this:
public class MyClassVisitor extends ClassVisitor < public MyClassVisitor(ClassVisitor cv) < super(Opcodes.ASM5, cv); >@Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) < MethodVisitor visitor = super.visitMethod( access, name, desc, signature, exceptions); if(method matches criteria) < visitor = new MyMethodVisitorAdapter(visitor); >return visitor; > >
try(FileInputStream in = new FileInputStream(new File("input.class")))
When chaining the visitors through the constructors, every method you don’t override will delegate to the chained visitor, replicating the original construct when the final target is a ClassWriter , resp. the MethodVisitor provided by the ClassWriter . If the method does not fulfill your transformation condition, so you return the original MethodVisitor , the optimization described above still applies. The method visitor follows the same pattern as the class visitor, overriding those method you want to intercept.
By the way, you should avoid mixing old I/O and NIO. A simplified variant of your code looks like
ClassReader classReader = new ClassReader(Files.readAllBytes(Paths.get("input.class"))); ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_FRAMES); classReader.accept(new MyClassVisitor(classWriter), ClassReader.SKIP_FRAMES); Files.write(Paths.get("output.class"), classWriter.toByteArray());
Note the symmetry between reading and writing
Though, when you use getResource et al, you might be forced to deal with InputStream . But for classes reachable through the system class loader, you can also just pass the class name to the ClassReader(String) constructor.